6

私は次のエンティティ構造を持っています:

   +-----------+                +-------------+        
   |  User     | -------------> |    Role     |
   +-----------+                +-------------+
                                       ^
                                       |
                               +-------+---------+
                               |                 |
                        +-----------+      +-----------+           +------------+
                        |   Role1   |      |  Role2    |-------->  | SomeEntity |
                        +-----------+      +-----------+           +------------+

Role2 が特定のプロパティ値を持つ SomeEntity を持つすべての User の名前を取得したいと考えています。JPA基準APIでこれを行う必要があります。

私がこれまでに行ったことは次のとおりです。

CriteriaBuilder cb = ...
CriteriaQuery<String> query = cb.createQuery(String.class);
Root<User> user = query.from(User.class);
SetJoin<User, Role> userRolesJoin = user.join(User_.roles);

// As you can see the userRolesJoin is of type Role and a Role doesn't have
// an property someEntity. So how to "cast" the userRolesJoin into an 
// SetJoin<User, Role2>.

ここでポリモーフィック クエリを実行する方法は? 助言がありますか?

残念ながら、JPA 基準 API は Hibernate の基準 API ほど直感的ではありません。

4

2 に答える 2

6

サブクエリを使用して解決しました

Role2 型に基づいてサブクエリを作成し、それを "SomeEntity" エンティティと結合して、述語を適用しました。次に、サブクエリの述語に一致する Role2.ids を使用して、サブクエリを「メイン」クエリに接続しました。

CriteriaBuilder cb = ...
CriteriaQuery<String> query = cb.createQuery(String.class);
Root<User> user = query.from(User.class);
SetJoin<User, Role> userRolesJoin = user.join(User_.roles);
Path<String> roleIdPath = userRolesJoin.get(User_.id);

Subquery<String> subquery = query.subquery(String.class);
Root<Role2> role2Root = subquery.from(Role2.class);
Join<Role2, SomeEntity> someEntityJoin = role2Root.join(Role2_.someEntity);
Path<String> someEntityPropertyPath = someEntityJoin.get(SomeEntity_.aProperty);
Predicate someEntityPropertyPredicate = cb.equal(someEntityPropertyPath,
            "a property value");
subquery.select(role2Root.get(Role2_.id));
subquery.where(someEntityPropertyPredicate);

In<String> idInSubqueryIds = cb.in(roleIdPath).value(subquery);

query.select(user.get(User_.username));
query.where(idInSubqueryIds);

EntityManager entityManager = ...;
TypedQuery<String> query = entityManager.createQuery(query);
List<String> usernames = query.getResultList();
于 2013-06-21T04:38:19.833 に答える
2

Criteria で as() を使用してキャストできます。

((Path)user.join(User_.roles).as(Role2.class)).join(Role2_.someEntity)

これは JPA 2.1 より前のプロバイダー固有のものかもしれませんが、JPA 2.1 では標準になっていると思います。

JPQLでは、TREAT操作を使用できます。

http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL#Special_Operators

2 番目の from() を使用することもできます。

Root<Role2> role2 = query.from(Role2.class);
... cb.equal(user.join(User_.roles), role2)
于 2013-06-20T13:54:40.410 に答える