HQL ビルダー (Hibernate クエリ言語) を探しています
質問
のビルダーを探しています 本社 ジャワでは。次のようなものを取り除きたいです。
StringBuilder builder = new StringBuilder()
.append("select stock from ")
.append( Stock.class.getName() )
.append( " as stock where stock.id = ")
.append( id );
むしろ次のようなものがいいでしょう:
HqlBuilder builder = new HqlBuilder()
.select( "stock" )
.from( Stock.class.getName() ).as( "stock" )
.where( "stock.id" ).equals( id );
少しグーグルで調べましたが、見つかりませんでした。
簡単で愚かなことを書きました HqlBuilder
現時点ではこれで私のニーズには合っていますが、私だけよりも多くのユーザーとテストを行っているものを見つけたいと思っています。
注記:Criteria API では実行できなかった次のようなことやその他のことを実行できるようにしたいと考えています。
select stock
from com.something.Stock as stock, com.something.Bonus as bonus
where stock.someValue = bonus.id
つまり。そのプロパティを持つすべての株式を選択します someValue
に指差す どれでも ボーナステーブルからのボーナス。
ありがとう!
解決
@セバスチャン・ロッカ・セラ
今、私たちは具体的なところに近づいています。あなたが行おうとしている種類の結合は、Criteria API では実際には可能ではありませんが、サブクエリでも同じことを達成できるはずです。まず、 DetachedCriteria
ボーナステーブルの場合は、 IN
の演算子 someValue
.
DetachedCriteria bonuses = DetachedCriteria.forClass(Bonus.class);
List stocks = session.createCriteria(Stock.class)
.add(Property.forName("someValue").in(bonuses)).list();
これは以下と同等です
select stock
from com.something.Stock as stock
where stock.someValue in (select bonus.id from com.something.Bonus as bonus)
唯一の欠点は、異なるテーブルへの参照がある場合です。 someValue
また、ID はすべてのテーブルで一意ではありません。しかし、あなたのクエリも同じ欠陥に悩まされるでしょう。
他のヒント
そうではありませんか 基準API 自分のためにやれ?それはあなたが求めているものとほぼ正確に似ています。
問題に対するタイプセーフなアプローチについては、次のことを検討してください。 クエリDSL.
クエリ例は次のようになります。
HQLQuery query = new HibernateQuery(session);
List<Stock> s = query.from(stock, bonus)
.where(stock.someValue.eq(bonus.id))
.list(stock);
Querydsl は、JPA2 と同様にコード生成に APT を使用し、JPA/Hibernate、JDO、SQL、および Java コレクションをサポートします。
私は Querydsl の管理者であるため、この回答には偏見があります。
別のタイプセーフなクエリ DSL については、次をお勧めします。 http://www.torpedoquery.org. 。このライブラリはまだ若いですが、エンティティのクラスを直接使用することでタイプ セーフを提供します。これは、リファクタリングまたは再設計の前にクエリが適用されなくなった場合の初期のコンパイラ エラーを意味します。
例もご紹介させていただきました。あなたの投稿から、サブクエリ制限を行おうとしていると思うので、それに基づいて例を作成しました。
import static org.torpedoquery.jpa.Torpedo.*;
Bonus bonus = from(Bonus.class);
Query subQuery = select(bonus.getId());
Stock stock = from(Stock.class);
where(stock.getSomeValue()).in(subQuery);
List<Stock> stocks = select(stock).list(entityManager);
Hibernate に組み込まれている Criteria クエリ API を使用したいようです。上記のクエリを実行するには、次のようになります。
List<Stock> stocks = session.createCriteria(Stock.class)
.add(Property.forName("id").eq(id))
.list();
Hibernate セッションにまだアクセスできない場合は、次のように「DetachedCriteria」を使用できます。
DetachedCriteria criteria = DetachedCriteria.forClass(Stock.class)
.add(Property.forName("id").eq(id));
特定の ID を持つボーナスを持つすべてのストックを取得したい場合は、次のようにすることができます。
DetachedCriteria criteria = DetachedCriteria.forClass(Stock.class)
.createCriteria("Stock")
.add(Property.forName("id").eq(id)));
詳細については、チェックアウトしてください 基準クエリ Hibernate ドキュメントより
select stock
from com.something.Stock as stock, com.something.Bonus as bonus
where stock.bonus.id = bonus.id
それは単なる結合です。Hibernate は、間のマッピングがある場合に限り、自動的にそれを実行します。 Stock
そして Bonus
セットアップと場合 bonus
のプロパティです Stock
. Criteria.list()
戻ります Stock
オブジェクトを呼び出すだけです stock.getBonus()
.
次のようなことをしたい場合は、注意してください
select stock
from com.something.Stock as stock
where stock.bonus.value > 1000000
使用する必要があります Criteria.createAlias()
. 。それは次のようなものでしょう
session.createCriteria(Stock.class).createAlias("bonus", "b")
.add(Restrictions.gt("b.value", 1000000)).list()
Criteria API は、HQL で使用できるすべての機能を提供するわけではありません。たとえば、同じ列に対して複数の結合を実行することはできません。
なぜ使わないのですか 名前付きクエリ?見た目がさらにすっきりしました:
Person person = session.getNamedQuery("Person.findByName")
.setString(0, "Marcio")
.list();
私は、状況に合わせて簡単に構築できる OMERO 用の GPL ソリューションを作成しました。
- ソース: QueryBuilder.java
- テスト: クエリビルダー模擬テスト
使用法:
QueryBuilder qb = new QueryBuilder();
qb.select("img");
qb.from("Image", "img");
qb.join("img.pixels", "pix", true, false);
// Can't join anymore after this
qb.where(); // First
qb.append("(");
qb.and("pt.details.creationTime > :time");
qb.param("time", new Date());
qb.append(")");
qb.and("img.id in (:ids)");
qb.paramList("ids", new HashSet());
qb.order("img.id", true);
qb.order("this.details.creationEvent.time", false);
「select->from->join->where->order」などのステートマシンとして機能します。オプションのパラメーターを維持します。Criteria API が実行できないクエリがいくつかありました (「 HHH-879)、そのため、最終的には、StringBuilder をラップするためにこの小さなクラスを作成する方が簡単でした。(注記:チケットがあります HHH-2407 この 2 つを統合する Hibernate ブランチについて説明します。その後、Criteria API を再度参照することがおそらく意味があるでしょう)
から利用可能な検索パッケージをご覧ください。 hibernate-generic-dao プロジェクト。これはかなりまともな HQL Builder 実装です。
このスレッドがかなり古いことは知っていますが、HqlBuilder も探していました。そして、これを見つけました 「スクリーンセーバー」プロジェクト
それはWindowsスクリーンセーバーではなく、」低分子および RNAi スクリーニングを実行するハイスループット スクリーニング (HTS) 施設向けのラボ情報管理システム (LIMS)。"
これには、非常に見栄えの良い HQLBuilder が含まれています。
利用可能なメソッドのサンプル リストを次に示します。
...
HqlBuilder select(String alias);
HqlBuilder select(String alias, String property);
HqlBuilder from(Class<?> entityClass, String alias);
HqlBuilder fromFetch(String joinAlias, String joinRelationship, String alias);
HqlBuilder where(String alias, String property, Operator operator, Object value);
HqlBuilder where(String alias, Operator operator, Object value);
HqlBuilder where(String alias1, Operator operator, String alias2);
HqlBuilder whereIn(String alias, String property, Set<?> values);
HqlBuilder whereIn(String alias, Set<?> values);
HqlBuilder where(Clause clause);
HqlBuilder orderBy(String alias, String property);
HqlBuilder orderBy(String alias, SortDirection sortDirection);
HqlBuilder orderBy(String alias, String property, SortDirection sortDirection);
String toHql();
...
スタンダードも登場しました JPA型金庫 クエリと標準的ではありませんが、それも良いです オブジェクトクエリ
例:
JPA型金庫
EntityManager em = ...
CriteriaBuilder qb = em.getCriteriaBuilder();
CriteriaQuery<Stock> c = qb.createQuery(Stock.class);
Root<Stock> = c.from(Stock.class);
Predicate condition = qb.eq(p.get(Stock_.id), id);
c.where(condition);
TypedQuery<Stock> q = em.createQuery(c);
List<Stock> result = q.getResultList();
オブジェクトクエリ
EntityManager em = ...
ObjectQuery<Stock> query = new GenericObjectQuery<Stock>(Stock.class);
Stock toSearch = query.target();
query.eq(toSearch.getId(),id);
List<Stock> res = (List<Stock>)JPAObjectQuery.execute(query, em);