私の質問は Java ジェネリックに関するものですが、JPA 関連のコードをいくつか入れて、実際のコンテキストを示します。
JPA 2.0 と Criteria API ベースのクエリを使用しています。すべてのクエリは同じパターンに従っています (単純な属性を比較します。パス ナビゲーションは必要ありません)。そのため、ビジネス ロジックを個別のクラスに保持しながら、JPA を処理するジェネリック クラスを作成しようとしています。私の目標は、エンティティ型と、基準を定義するペア (フィールド名 -> 目的の値) を格納するマップを指定して、いくつかのエンティティ フィールドの値を持つ Bean (または Bean のコレクション) を返すメソッドを持つことです。 .
すべてのエンティティがPersistible
インターフェイスを実装し、転送オブジェクトはすべて から継承しQueryBean
ます。これらのクラスは問題に関係がないと考えているため、コードをスキップしています。
次のコードは、私の最初のアプローチのスニペットです (cb が有効な CriteriaBuilder インスタンスであると仮定してください)。
protected <T extends QueryBean, TT extends Persistible> Collection<T> executeQueryEntity
(Class<T> type, Class<TT> rootType, QueryConfig queryConfig, Map<String, Object> parameters) {
// (...) Initialization goes here
CriteriaQuery<T> c = cb.createQuery(type);
// FROM CLAUSE
Root<TT> root = c.from(rootType);
// SELECT CLAUSE
List<String> constructorParams = queryConfig.getTargetAttributes();
Selection<?>[] selectArray = new Selection<?>[constructorParams.size()];
for (int i = 0; i < constructorParams.size(); i++) {
selectArray[i] = root.get(constructorParams.get(i));
}
c.select(cb.construct(type, selectArray));
// WHERE CLAUSE
for (String filter : parameters.keySet()) {
if (queryConfig.getFieldConfiguration().get(filter).compareUsingEquals()) {
// SOME PREDICATE
}
else {
// SOME OTHER PREDICATE
}
}
// (...) Rest of the code goes here
}
私の QueryConfig インターフェイスは次のとおりです。
public interface QueryConfig {
List<String> getTargetAttributes();
Map<String, FieldConfiguration> getFieldConfiguration();
}
クエリに関する情報 (QueryBean コンストラクターに必要なパラメーターやエンティティ フィールドに関する情報など) を提供するクラスを既に使用しているQueryConfig
ため、エンティティ型を次のように渡すのではなく、そのクラスから取得するとよいと考えました。クラス パラメータ。この質問から直接行うことはできないと推測するので、次の回避策を試しました。
次のように QueryConfig にメソッドを追加します。
Class< ? extends Persistible> getTargetEntity();
次のような中間メソッドを追加します。
public <T extends QueryBean> Collection<T> queryMany(Class<T> type, QueryConfig config, Map<String, Object> parameters) {
executeQueryEntity(type, config.getTargetEntity(), parameters);
}
しかし、それはコンパイルされません。理由はここで説明されていると思います:クラスジェネリックの型の不一致ですが、実際には答えがわかりませんでした。Class< TT >
私の質問は:パラメータを execute メソッドに渡さないようにする方法はありますか? これは問題に対処する良い方法ですか、それとも全体をリファクタリングする必要がありますか? コードの改善も大歓迎です!