2012-01-06 10 views
11

GlassFishとJSFを使用して最初のJava EE Webアプリケーションを構築しています。私は基準クエリにかなり新しいです。私は実行する必要があるクエリを持っていますが、javaee6チュートリアルは例では少し薄いようです。とにかく、私は質問を作成するのに苦労している。JPA基準の作成に関するヘルプが必要です

目標:保存されているほとんどのドキュメントを会社に引き渡したい。 企業はDocumentsとOneToMany関係を持っています。 ドキュメントには複数のテーブルを持つManyToOne関係があり、 "usertype"列でそれらが区別されます。

MySQLのクエリ:

SELECT USERID, COUNT(USERID) AS CNT 
FROM DOCUMENTS 
WHERE USERTYPE="COMPANY" 
GROUP BY USERID 
ORDER BY CNT DESC 

おかげ

--update-- ユーザーからのフィードバックに基づき、ここで私がこれまで持っているものです。

 CriteriaBuilder cb = em.getCriteriaBuilder(); 
     CriteriaQuery<Documents> cqry = cb.createQuery(Documents.class); 
     //Intersting Stuff 
     Root<Documents> root = cqry.from(Documents.class); 
     Expression userid = root.get("userID"); 
     Expression usertype = root.get("userType"); 
     Expression count = cb.count(userid); 
     cqry.multiselect(userid, count); 
     Predicate userType = cb.equal(usertype, "COMPANY"); 
     cqry.where(userType); 
     cqry.groupBy(userid); 
     cqry.orderBy(cb.desc(count)); 
     //more boilerplate 
     Query qry = em.createQuery(cqry); 
     List<Documents> results = qry.getResultList(); 

私が手にエラーがされます:

Exception Description: Partial object queries are not allowed to maintain the cache or be edited. You must use dontMaintainCache(). 

典型的なエラーは、私に何の意味もありません!

+0

CriteriaQuery からCriteriaQueryへのクエリのタイプを解除して、APIの問題を起こすことなくカウントを選択してみます。あなたがテーブル/エンティティに関する情報を他にも投稿しているなら、私は他の方法を試すことができます – perissf

答えて

20

あなたのクエリは、(あなたがyadayadapartialyadayadaをというエラーを取得している理由です)完全エンティティオブジェクトを返しません。

あなたの解決策はほぼ正しいです。変更する必要があります。部分です。代わりにあなたがCriteriaBuilder.createTupleQuery()を呼び出すことによってタプルCriteriaQuery<..>を作成する必要がCriteriaQuery<...>平野の

。私は「didnの場合(基本的に、あなたはCriteriaBuilder.createQuery(...)を呼び出し、引数としてTuple.classを渡すことができます。Tupleワイルドカードエンティティクラスの一種である。)Tuple

CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<Tuple> cq= cb.createTupleQuery(); 

Root<Documents> root = cq.from(Documents.class); 
Expression<Integer> userId = root.get("USERID"); 
Expression<String> userType = root.get("USERTYPE"); 
Expression<Long> count = cb.count(userId); 

cq.multiselect(userId.alias("USERID"), count.alias("CNT")); 
cq.where(cb.equal(userType, "COMPANY"); 
cq.groupBy(userId); 
cq.orderBy(cb.desc(count)); 

TypedQuery<Tuple> tq = em.createQuery(cq); 
for (Tuple t : tq.getResultsList()) { 
    System.out.println(t.get("USERID")); 
    System.out.println(t.get("CNT")); 
} 

(アクセスフィールドは私にエラーを与えました彼らのためにトンの使用別名(multiselect(...)で)。私は別名を使用してきた理由ですが、これはかなり徹底的に仕様書に記述されているJPA 2のメタモデルAPIを、使用することによって、よりきれいに取り組むことができます。

のドキュメントCriteriaQuery.multiselect(...)は、Tupleオブジェクトをより深く使用するクエリの動作を記述します。

+0

華麗!それはほとんどの箱のすぐ近くで働いた。これと@Mechkovを共有した記事の間に、私は基準クエリーをもっとよく理解しています。ありがとうございました。 –

+0

良い答えは、次のエラーで私の問題を解決するのに役立った 'dontMaintainCache()'を使用する必要があります – user75ponic

+0

あなたのコード例ありがとうございます。私は、(エンティティの代わりに)タプルを使ってjpa criteriaクエリについてたくさん学んできました。 – hbobenicio

0

この簡単なチュートリアルをご覧ください。それはJPA2と基準

http://www.jumpingbean.co.za/blogs/jpa2-criteria-api

よろしくを使用しています!

+1

あなたが投稿したチュートリアルはうまくいきますが、OPが望むクエリは興味深い質問をします:タイプ? – perissf

+0

ありがとう、チュートリアルは私の多くを助けた。私が必要とするタイプは、id(long)です。 –

+0

Cool。それが助けてくれてうれしい。あまりにもずっと前に私はそれを自分で使いました。 – Mechkov

2

あなたが休止状態を使用している場合は、この作業をする必要があります:

ProjectionList pl = Projections.projectionList() 
.add(Projections.groupProperty("userid")) 
.add(Projections.property("userid")) 
.add(Projections.count("userid")); 

Criteria criteria = session.createCriteria(Document.class) 
.add(Restrictions.eq("usertype",usertype)) 
.setProjection(pl) 
.addOrder(Order.desc("cnt")); 

はそれが役に立てば幸い!あなたが唯一の特定のテーブルの二つのフィールドを選択しているよう

+0

これは、ここでは範囲外のHiberateを使用することを意味します。あなたは少なくともこれに言及すべきです。 – perissf

+0

はい、私はHibernateを使用していないのではないかと心配しています。それでも私は私がいたいと思っています! –

+0

ああ、大きなお詫び申し上げます。それを知らなかった! – Gonzalo

関連する問題