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 构造函数表达式不能使用构造函数的主要内容,如果未能解决你的问题,请参考以下文章

微信小程序--箭头表达式

JPQL:在构造函数表达式中接收集合

使用 Clojure reify 提供构造函数

C# 构造函数总结

C# 构造函数总结

行构造函数表达式选择不使用索引