0

2つのオブジェクトがあり、どちらもエンティティとして定義されており、一方には次のようにもう一方が含まれています。

@Entity
public class TestC 
{
    @Id @GeneratedValue
    private Integer id;
    @ManyToOne (cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
    TestD d;
} 

@Entity
public class TestD 
{
    @Id @GeneratedValue
    private Integer id;
    String moo;
}    

エンティティは永続化されます:

TestC c2 = new TestC();
TestD d2 = new TestD();
d2.moo = "d2";
c2.d = d2;
em.getTransaction().begin();
em.persist(d2);
em.persist(c2);
em.getTransaction().commit();

TestDのインスタンスを使用してTestCオブジェクトをクエリしようとしています。

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<TestC> query = builder.createQuery(TestC.class);
Root<TestC> from = query.from(TestC.class);

ParameterExpression<TestD> pe = builder.parameter(TestD.class);

query.where(builder.equal(pe, from.<TestD>get("d")));

TestC found = em.createQuery(query)
    .setParameter(pe, d2)
    .getSingleResult();

ただし、EclipseLinkは、クエリの実行時に次のエラーを発生させます(「(?=)」の近くではSQLが無効であり、TestDオブジェクトの列名がないことに注意してください)。

Exception in thread "main" Local Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Invalid argument value: java.io.NotSerializableException
Error Code: 0
Call: SELECT t1.ID, t1.D_ID FROM TESTD t0, TESTC t1 WHERE ((? = ) AND (t0.ID = t1.D_ID))
bind => [1 parameter bound]
Query: ReadAllQuery(referenceClass=TestC sql="SELECT t1.ID, t1.D_ID FROM TESTD t0, TESTC t1 WHERE ((? = ) AND (t0.ID = t1.D_ID))")

クエリを間違って作成していますか?

助けてくれてありがとう!

4

1 に答える 1

1

JavaDocには記載されていませんが、ParameterExpression は 2 番目の引数である必要があります。順序はequal(Expression x, java.lang.Object y) と同じロジックに従います。さらに、 .selectが必要です。EclipseLink (少なくとも 2.3.0) はなくても動作しますが、仕様に従って select/multiselect を除外することは移植性がありません。

ポータブル アプリケーションでは、select または multiselect メソッドを使用して、クエリの選択リストを指定する必要があります。これらの方法のいずれも使用しないアプリケーションは移植できません。

これらの変更の後、正しいアプローチは次のとおりです。

CriteriaQuery<TestC> query = builder.createQuery(TestC.class);
Root<TestC> from = query.from(TestC.class);

ParameterExpression<TestD> pe = builder.parameter(TestD.class);
query.select(from)
     .where(builder.equal(from.<TestD>get("d"), pe));

TestC found = em.createQuery(query)
                .setParameter(pe, d)
                .getSingleResult();
于 2012-05-01T15:39:11.310 に答える