JPA 2 构造函数表达式不能使用构造函数
Posted
技术标签:
【中文标题】JPA 2 构造函数表达式不能使用构造函数【英文标题】:JPA 2 Constructor Expression cannot use constructor 【发布时间】:2014-01-31 08:11:17 【问题描述】:我在 WebSphere Application Server 8 上使用 OpenJPA 2.1.1。
我想使用构造函数表达式从 SELECT 查询创建对象:
String queryString = "SELECT NEW mypackage.StatisticDataObject(c.source, "
+ "SUM(CASE WHEN (c.validTo <= CURRENT_TIMESTAMP AND c.expireNoProblem LIKE 'N') THEN 1 ELSE 0 END ), "
+ "SUM(CASE WHEN (c.validTo <= CURRENT_TIMESTAMP AND c.expireNoProblem LIKE 'Y') THEN 1 ELSE 0 END ), "
+ "SUM(CASE WHEN (c.validTo > :timestamp30 ) THEN 1 ELSE 0 END ), "
+ "SUM(CASE WHEN (c.validTo > :timestamp10 AND c.validTo <= :timestamp30 ) THEN 1 ELSE 0 END ), "
+ "SUM(CASE WHEN (c.validTo > CURRENT_TIMESTAMP AND c.validTo <= :timestamp10 ) THEN 1 ELSE 0 END ) )"
+ "FROM MYTABLE c GROUP BY c.source";
TypedQuery<StatisticDataObject> q = em.createQuery(queryString,
StatisticDataObject.class);
q.setParameter("timestamp30", getTimestampIn(30));
q.setParameter("timestamp10", getTimestampIn(10));
构造函数:
public StatisticDataObject(String name, Integer expired,
Integer expiredButOK, Integer expireIn10Days, Integer expireIn30Days,
Integer expireGT30Days)
this.name = name;
this.expired = expired;
this.expiredButOK = expiredButOK;
this.expireIn10Days = expireIn10Days;
this.expireIn30Days = expireIn30Days;
this.expireGT30Days = expireGT30Days;
但我得到以下异常:
Caused by: <openjpa-2.1.1-SNAPSHOT-r422266:1141200 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: Query "SELECT NEW mypackage StatisticDataObject(c.source, ... at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:872)
at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:794)
at org.apache.openjpa.kernel.DelegatingQuery.execute(DelegatingQuery.java:542)
at org.apache.openjpa.persistence.QueryImpl.execute(QueryImpl.java:315)
at org.apache.openjpa.persistence.QueryImpl.getResultList(QueryImpl.java:331)
...
Caused by: java.lang.RuntimeException: Es wurde kein Konstruktor für "class mypackage.StatisticDataObject" mit den Argumenttypen "[class java.lang.String, class java.lang.String, class java.lang.String, class java.lang.String, class java.lang.String, class java.lang.String]" gefunden, um die Daten einzutragen.
// ENGLISH Translation: Caused by: java.lang.RuntimeException: There is no constructor "class mypackage.StatisticDataObject" with argument type "[class java.lang.String, class java.lang.String, class java.lang.String, class java.lang.String, class java.lang.String, class java.lang.String]".
at org.apache.openjpa.kernel.FillStrategy$NewInstance.findConstructor(FillStrategy.java:139)
at org.apache.openjpa.kernel.FillStrategy$NewInstance.fill(FillStrategy.java:144)
at org.apache.openjpa.kernel.ResultShape.pack(ResultShape.java:362)
at org.apache.openjpa.kernel.ResultShapePacker.pack(ResultShapePacker.java:48)
at org.apache.openjpa.kernel.QueryImpl$PackingResultObjectProvider.getResultObject(QueryImpl.java:2082)
at org.apache.openjpa.lib.rop.EagerResultList.<init>(EagerResultList.java:36)
at org.apache.openjpa.kernel.QueryImpl.toResult(QueryImpl.java:1251)
at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:1007)
at org.apache.openjpa.kernel.QueryImpl.execute(QueryImpl.java:863)
... 84 more
如果我在没有 NEW mypackage.StatisticDataObject() 的情况下运行查询,则可以使用 Object[]。 object[1-5] (.getClass()) 的类也是 Integer。
那么为什么JPA在使用构造函数表达式的时候会从SUM()返回一个String而不是Integer呢?
【问题讨论】:
【参考方案1】:在您的构造函数中,您将应用 SUM 的字段类型的状态需要为数字,并且结果类型必须与字段类型相对应。例如,如果对 Double 字段求和,则结果将作为 Double, 返回。如果对 Long 字段类型求和,则响应将作为 Long 返回。
这是问题的根本原因,SUM 没有返回 Integer 类型。
【讨论】:
没错,SUM 似乎返回了一个字符串。但为什么呢?以上是关于JPA 2 构造函数表达式不能使用构造函数的主要内容,如果未能解决你的问题,请参考以下文章