お世話になっております。
Daoクラスをテンプレート化するために親クラスを作成しているのですが
境界型ジェネリクスで型を指定する際に以下のEからどのように型を取得すればいいのでしょうか?
lang
1 2abstract public class BaseDao<E extends BaseEntity> { 3 4 protected static void findAll(String sql) throws Exception { 5 Connection con = getConnect(); 6 7 RowProcessor rp = new BasicRowProcessor(new MyBeanProcessor()); 8 QueryRunner qr = new QueryRunner(); 9 10 ResultSetHandler<List<E>> h = new BeanListHandler<E>(E.class, rp);// E.classがコンパイルエラー 11 List<E> list = qr.query(con, sql, h); 12 con.close(); 13 } 14~省略~ 15}
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
クラス名などから察するに、Commons-dbutilsをお使いなのだと思いますが(違っていたらすみません)
Commons-dbutilsでDAOを作る場合には、便利な実装例があります。
Apache Commons公式|DbUtils: JDBC Utility Component Examples
クエリを投げるクラスと、結果1行ごとに制御するハンドラとを分けると、例えば以下のようにすると良いでしょうか。
あとは、型情報(ここでは T)はインスタンス化できないので、引数に追加してあげると良いでしょう。
java
1import java.sql.SQLException; 2import java.util.List; 3 4import javax.sql.DataSource; 5 6import org.apache.commons.dbutils.QueryRunner; 7import org.apache.commons.dbutils.ResultSetHandler; 8import org.apache.commons.dbutils.handlers.BeanListHandler; 9 10public class BaseDataAccessObject<T> { 11 12 private DataSource dataSource = null; 13 14 public List<T> findAll(String queryString,Class<T> clazz) throws SQLException { 15 ResultSetHandler<List<T>> h = new BeanListHandler<T>(clazz); 16 17 QueryRunner run = new QueryRunner(dataSource); 18 19 List<T> result = run.query(queryString, h, "PlaceHolder"); 20 21 return result; 22 } 23}
投稿2017/02/04 09:56
総合スコア12011
0
- 一番簡単な方法
このクラスのコンストラクターに派生クラスからEのクラスを渡してこのクラスのフィールドに覚えておく。
- リフレクションを使う(条件付き)
細かな条件を忘れたのですが・・・(^^;
例えばこのクラスの派生クラスをnew DerivedDao<DerivedEntry>() {};
のように無名クラスとして生成してやるとリフレクションで型引数のクラスを実行時に参照できます。無名クラスにせずにインスタンスを生成すると型が消去されてしまうのでリフレクションでも参照できません。
java
1abstract public class BaseDao<E extends BaseEntity> { 2 final Class<E> classE; 3 4 BaseDao() { 5 ParameterizedType superType = 6 (ParameterizedType)getClass().getGenericSuperclass(); 7 Type[] atvs = superType.getActualTypeArguments(); 8 classE = (Class<E>)atvs[0]; 9 } 10}
このコードではBaseDaoを直接継承したクラス(無名クラスとか)しかないと前提を置いてます。
派生の派生・・・というふうに継承が深くなるともう少し配慮が必要だと思います。
無名クラスで取れるのでclass DerivedDao extends BaseDao<DerivedEntity> { ... }
のように普通に派生クラスを定義しても同じ方法でクラスが参照できると思います。
投稿2017/02/04 09:14
編集2017/02/04 09:20総合スコア18394
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/02/04 10:16
2017/02/04 10:26
0
ベストアンサー
基本的はジェネリクスは抽象的に扱うものであって実態やクラスは取得できません。
必要になってしまった場合には設計を見直すべきです。
一応裏技的な解決策はありますが、あまりいいソースとは言えません...
java
1Class<?> clazz = this.getClass(); 2Type type = clazz.getGenericSuperclass(); 3ParameterizedType pt = (ParameterizedType)type; 4Type[] actualTypeArguments = pt.getActualTypeArguments(); 5Class<?> entityClass = (Class<?>)actualTypeArguments[0];
追記
java
1abstract public class BaseDao { 2 3 protected static <E extends BaseEntity> void findAll(String sql) throws Exception { 4 Connection con = getConnect(); 5 6 RowProcessor rp = new BasicRowProcessor(new MyBeanProcessor()); 7 QueryRunner qr = new QueryRunner(); 8 9 ResultSetHandler<List<E>> h = new BeanListHandler<E>(getEntityClass(), rp);// E.classがコンパイルエラー 10 List<E> list = qr.query(con, sql, h); 11 con.close(); 12 } 13 14 protected abstruct <E extends BaseEntity> Class<E> getEntityClass(); 15~省略~ 16}
とかですかね?実装クラスではgetEntityClass()を記載する必要がありますが、クラスの総称型を書く必要がなくなります。
投稿2017/02/04 09:03
編集2017/02/04 09:54総合スコア310
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/02/04 09:36
2017/02/04 09:49
2017/02/04 10:08
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/02/04 10:10