32

基準を使用して次のクエリを作成したいと考えています。EmbeddedIdが定義されたエンティティがあります。

 @Entity
 @Table(name="TB_INTERFASES")
 public class Interfase implements Serializable {

  @EmbeddedId
  private InterfaseId id;
 }

 @Embeddable
 public class InterfaseId implements Serializable {
  @Column(name="CLASE")
  private String clase;
 }

そして、私がやろうとしている基準クエリは次のとおりです。

 CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
 CriteriaQuery<Interfase> criteriaQuery = criteriaBuilder.createQuery(Interfase.class);
 Root<Interfase> entity = criteriaQuery.from(Interfase.class);
 criteriaQuery.where(
   criteriaBuilder.equal(entity.get("clase"), "Clase"),
 );

しかし、これは IllegalArgumentException をスローしています。

java.lang.IllegalArgumentException: Not an managed type: class InterfaseId

私もこのクエリで試しました:

 Root<Interfase> entity = criteriaQuery.from(Interfase.class);
 criteriaQuery.where(
   criteriaBuilder.equal(entity.get("id").get("clase"), "Clase"),
 );

そしてこれも…

 Root<Interfase> entity = criteriaQuery.from(Interfase.class);
 criteriaQuery.where(
   criteriaBuilder.equal(entity.get("id.clase", "Clase"),
 );

運がない。私の質問は、クラスが Embedded および EmbeddedId アノテーションを使用している場合、基準を使用してクエリを作成するにはどうすればよいですか?

ありがとう!。マウロ。

4

3 に答える 3

65

の属性にアクセスするには、パス ナビゲーションを使用する必要がありますEmbeddable。JPA 2.0仕様の例を次に示します(静的メタモデルを使用):

6.5.5 パスナビゲーション

...

次の例で ContactInfoは、 は住所と一連の電話で構成される組み込み可能なクラスです。Phoneエンティティです。

CriteriaQuery<Vendor> q = cb.createQuery(Vendor.class);
Root<Employee> emp = q.from(Employee.class);
Join<ContactInfo, Phone> phone =
    emp.join(Employee_.contactInfo).join(ContactInfo_.phones);
q.where(cb.equal(emp.get(Employee_.contactInfo)
                    .get(ContactInfo_.address)
                    .get(Address_.zipcode), "95054"))
    .select(phone.get(Phone_.vendor));

次の Java Persistence クエリ言語クエリは同等です。

SELECT p.vendor
FROM Employee e JOIN e.contactInfo.phones p
WHERE e.contactInfo.address.zipcode = '95054'

したがって、あなたの場合、次のようなものが必要になると思います。

criteriaBuilder.equal(entity.get("id").get("clase"), "Referencia 111")

参考文献

  • JPA 2.0 仕様
    • 6.5.5項「パスのナビゲーション」

更新:提供されたエンティティを Hibernate EntityManager 3.5.6 と次のクエリでテストしました。

CriteriaBuilder builder = em.getCriteriaBuilder();

CriteriaQuery<Interfase> criteria = builder.createQuery(Interfase.class);
Root<Interfase> interfaseRoot = criteria.from(Interfase.class);
criteria.select(interfaseRoot);
criteria.where(builder.equal(interfaseRoot.get("id").get("clase"), 
    "Referencia 111"));

List<Interfase> interfases = em.createQuery(criteria).getResultList();

正常に実行され、次の SQL が生成されます。

17:20:26.893 [メイン] DEBUG org.hibernate.SQL -
    選択する
        interfase0_.CLASE を CLASE31_ として
    から
        TB_INTERFASES インターフェイス0_
    どこ
        インターフェイス0_.CLASE=?
17:20:26.895 [main] TRACE org.hibernate.type.StringType - 'Referencia 111' をパラメーターにバインド: 1

期待どおりに動作します。

于 2010-11-03T06:19:25.440 に答える
0

それは古い質問ですが、とにかく...

別の非常に簡単な解決策は、

InterfaseId id = new InterfaseId();
id.setClase("Clase");
Interfase found = em.find(id);

あなたが求めたこと以外のことをしようとしている場合を除いて、これはそれを行うための「正気の」方法です. ID に対するクエリは、最大 1 つの結果を返します。

于 2016-10-17T21:27:51.450 に答える
0

エンティティが保存されているフォルダと同じフォルダにクラスをコピーして貼り付けてみてくださいmetamodel(NetBeans 8.2 では、クラスは自動的に生成され、エンティティと同じ名前になりますが、最後にアンダースコアが付きます。 と のようInterfase_になりInterfaseId_ます)。

metamodelクラスInterfase_のインポートを強制InterfaseId_し、目的のフィールドを参照します。

CriteriaBuilder builder = em.getCriteriaBuilder();

CriteriaQuery<Interfase> criteria = builder.createQuery(Interfase.class);
Root<Interfase> interfaseRoot = criteria.from(Interfase.class);
criteria.select(interfaseRoot);
criteria.where(builder.equal(interfaseRoot.get(Interfase_.id).get(InterfaseId_.clase),"Referencia 111"));
List<Interfase> interfases = em.createQuery(criteria).getResultList();
于 2017-12-07T18:13:21.573 に答える