2012-05-01 2 views
0

잘못된 SQL을 생성, 모두 정의 엔티티로, 다른 사람을 포함하는 하나는 다음과 같이은 EclipseLink JPA CriteriaBuilder 내가 두 개체가 구문

@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))") 

내가 잘못 쿼리를 건물입니다 어떤 도움

감사

+0

객체가 난 여전히 SQL 구문 오류를 (내가 MySQL을 사용하고 있습니다) 얻을 직렬화 구현하는 경우에도 : 내부 예외 : com.mysql.jdbc .exceptions.jdbc4.MySQLSyntaxErrorException : SQL 구문에 오류가 있습니다. 올바른 구문을 찾으려면 MySQL 서버 버전에 해당하는 매뉴얼을 확인하십시오. ') AND (t0.ID = t1.D_ID))'1 '에서 사용하십시오. – user1241043

답변

1

그것은이 JavaDoc 설명되어 있지 않습니다, 그러나 ParameterExpression은 두 번째 인수 여야합니다. 주문은 equal (Expression x, java.lang.Object y)과 동일한 논리를 따르며, .select이 필요합니다. EclipseLink (최소 2.3.0 이상)는 사양에 따라 작동하지만 사양에 따라 선택/다중 선택 떠나기 밖으로 선택하는 것은 휴대용되지 않습니다 :

휴대용 응용 프로그램은 쿼리의 선택 목록을 지정 에 선택 또는 다중 선택 방법을 사용합니다. 이러한 방법 중 하나를 사용하지 않는 응용 프로그램은 이식 가능하지 않습니다.

이러한 변경 한 후, 올바른 방법은 다음과 같습니다

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(); 
+0

감사합니다 !!()가 문제를 해결 한 매개 변수 순서를 전환합니다 (결코 고려하지 않음). 흥미롭게도 Hibernate는 매개 변수와 함께 잘못된 방식으로 작업했습니다. – user1241043

+0

좋습니다. 나에겐 Hibernate가 옳다고 보인다. 왜냐하면이 순서는 문서화되어 있지 않기 때문이다. –