我的JPA 2.1查询有问题,但我不明白。我有以下实体:
@Entity
@Table
public class DocumentEntity {
@Id
private Integer id;
@OneToMany(mappedBy = "document", cascade = CascadeType.ALL)
private Set<AttributeEntity<?>> attributes;
...
}
AbstractEntity
@Entity
@Table
@Inheritance
@DiscriminatorColumn(name = "type")
public abstract class AttributeEntity<T> {
@Id
private Integer id;
@Column
@NotBlank
private String name;
@ManyToOne
@JoinColumn(name = "document_id")
private DocumentEntity document;
... getters and setters
public abstract T getValue();
public abstract void setValue(T value);
}
AbstractDateEntity
@Entity
@DiscriminatorValue("date")
public class AttributeDateEntity extends AttributeEntity<Date> {
@Column(name = "date_value")
@NotNull
private Date value;
@Override
public Date getValue() {
return value;
}
@Override
public void setValue(Date value) {
this.value = value;
}
}
AbstractStringEntity
@Entity
@DiscriminatorValue("string")
public class AttributeStringEntity extends AttributeEntity<String> {
@Column(name = "string_value")
@NotNull
private String value;
@Override
public String getValue() {
return value;
}
@Override
public void setValue(String value) {
this.value = value;
}
}
如您所见,文档可以有多个属性。这些属性有一个类型(字符串,日期,...)。在这里我的DAO课程:
public class DocumentDao {
public List<DocumentEntity> find(Date from, Date to, String invoiceNumber) {
StringBuilder queryString = new StringBuilder("SELECT d FROM DocumentEntity d ");
if (from != null) {
queryString.append("INNER JOIN TREAT(d.attributes as AttributeDateEntity) a1 WITH a1.name = 'from' AND a1.value >= :from ");
}
if (to != null) {
queryString.append("INNER JOIN TREAT(d.attributes as AttributeDateEntity) a2 WITH a2.name = 'to' AND a2.value <= :to ");
}
if (invoiceNumber != null) {
queryString.append("INNER JOIN TREAT(d.attributes as AttributeStringEntity) a3 WITH a3.name = 'invoiceNumber' AND a3.value = :invoiceNumber ");
}
Query query = getEntityManager().createQuery(queryString.toString());
if (from != null) {
query.setParameter("from", from);
}
if (to != null) {
query.setParameter("to", to);
}
if (invoiceNumber != null) {
query.setParameter("invoiceNumber", invoiceNumber);
}
return query.getResultList();
}
}
但是当我从单元测试中使用这种方法时,例如:
@Test
public void testFind() throws Exception {
dao.find(new Date(), null, "test");
}
我有以下例外:
Caused by: java.lang.IllegalArgumentException: Parameter value [Tue Aug 02 10:25:36 CEST 2016] did not match expected type [java.lang.String (n/a)]
at org.hibernate.jpa.spi.BaseQueryImpl.validateBinding(BaseQueryImpl.java:874) [hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.jpa.internal.QueryImpl.access$000(QueryImpl.java:80) [hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.jpa.internal.QueryImpl$ParameterRegistrationImpl.bindValue(QueryImpl.java:248) [hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.jpa.spi.BaseQueryImpl.setParameter(BaseQueryImpl.java:620) [hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:180) [hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:49) [hibernate-entitymanager-4.3.10.Final.jar:4.3.10.Final]
at com.actility.energy.customer.area.dao.DocumentDaoBean.buildQuery(DocumentDaoBean.java:197) [customer-area-ejb.jar:]
at com.actility.energy.customer.area.dao.DocumentDaoBean.find(DocumentDaoBean.java:147) [customer-area-ejb.jar:]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.8.0_65]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) [rt.jar:1.8.0_65]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.8.0_65]
at java.lang.reflect.Method.invoke(Method.java:497) [rt.jar:1.8.0_65]
at org.jboss.as.ee.component.ManagedReferenceMethodInterceptor.processInvocation(ManagedReferenceMethodInterceptor.java:52)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:437)
at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.doMethodInterception(Jsr299BindingsInterceptor.java:82) [wildfly-weld-9.0.2.Final.jar:9.0.2.Final]
at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.processInvocation(Jsr299BindingsInterceptor.java:93) [wildfly-weld-9.0.2.Final.jar:9.0.2.Final]
at org.jboss.as.ee.component.interceptors.UserInterceptorFactory$1.processInvocation(UserInterceptorFactory.java:63)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.component.invocationmetrics.ExecutionTimeInterceptor.processInvocation(ExecutionTimeInterceptor.java:43) [wildfly-ejb3-9.0.2.Final.jar:9.0.2.Final]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.jpa.interceptor.SBInvocationInterceptor.processInvocation(SBInvocationInterceptor.java:47) [wildfly-jpa-9.0.2.Final.jar:9.0.2.Final]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:437)
at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:64) [weld-core-impl-2.2.16.SP1.jar:2015-09-16 08:49]
at org.jboss.as.weld.ejb.EjbRequestScopeActivationInterceptor.processInvocation(EjbRequestScopeActivationInterceptor.java:83) [wildfly-weld-9.0.2.Final.jar:9.0.2.Final]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ee.concurrent.ConcurrentContextInterceptor.processInvocation(ConcurrentContextInterceptor.java:45) [wildfly-ee-9.0.2.Final.jar:9.0.2.Final]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.InitialInterceptor.processInvocation(InitialInterceptor.java:21)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
at org.jboss.as.ee.component.interceptors.ComponentDispatcherInterceptor.processInvocation(ComponentDispatcherInterceptor.java:52)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.component.interceptors.NonPooledEJBComponentInstanceAssociatingInterceptor.processInvocation(NonPooledEJBComponentInstanceAssociatingInterceptor.java:59) [wildfly-ejb3-9.0.2.Final.jar:9.0.2.Final]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInCallerTx(CMTTxInterceptor.java:254) [wildfly-ejb3-9.0.2.Final.jar:9.0.2.Final]
... 150 more
我不明白为什么要String
而不是Date
。