JPA CriteriaQuery 无法为日期差异之和找到合适的构造函数

JPA CriteriaQuery Unable to locate appropriate constructor for sum of date diffrerence

我知道这个问题看起来很相似,但我认为情况不同

这是异常消息

Exception while fetching data (/periodicReport/userReport) : org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [com.analytics.entity.projections.UserParticipantCountAndDurationImpl]. Expected arguments are: java.util.UUID, long, java.util.Date [select new com.analytics.entity.projections.UserParticipantCountAndDurationImpl(generatedAlias0.userID, count(distinct generatedAlias0.userID), sum(function('TIMEDIFF', generatedAlias0.endTime, generatedAlias0.startTime))) from com.analytics.entity.ConferenceParticipant as generatedAlias0 group by generatedAlias0.userID order by :param0 desc]

我希望总和为 Long,并且我已在条件查询中指定了它。 我不知道在哪里定义日期

构建者的代码片段

Expression<Long> sum = criteriaBuilder.sum(
            criteriaBuilder.function(
                    "TIMEDIFF",
                    Long.class,
                    participantRoot.<Date>get("endTime"),
                    participantRoot.<Date>get("startTime")
            )
    );
    Expression<Long> count = criteriaBuilder.countDistinct(participantRoot.get("userID"));
    reportQuery.select(criteriaBuilder.construct(
            UserParticipantCountAndDurationImpl.class,
            participantRoot.get("userID").as(UUID.class).alias(USER_ID),
            count.as(Long.class).alias(PARTICIPANTS),
            sum.as(Long.class).alias(PARTICIPANT_DURATION)
    ));

有问题的class

@Data
@NoArgsConstructor
public class UserParticipantCountAndDurationImpl implements UserParticipantCountAndDuration, Serializable {

   private UUID userID;

   private long participants;

   public long participantDuration;

   public UserParticipantCountAndDurationImpl(
           UUID userID,
           long participants,
           long participantDuration
   ) {
       this.userID = userID;
       this.participants = participants;
       this.participantDuration = participantDuration;
   }
}

是的,我已经尝试更改构造函数的签名。在这种情况下,查询将 运行,但随后会抛出 CastException,因为它 java.util.Date

您需要一个带有要从 timediff 函数中提取的单位名称的表达式

public static class TimeUnitExpression extends BasicFunctionExpression<String> implements Serializable {

    public TimeUnitExpression(CriteriaBuilderImpl criteriaBuilder, Class<String> javaType,
            String functionName) {
        super(criteriaBuilder, javaType, functionName);
    }

    @Override
    public String render(RenderingContext renderingContext) {
        return getFunctionName();
    }
}

所以你的求和表达式变成了

    Expression<Long> sum = criteriaBuilder.sum(
            criteriaBuilder.function(
                    "TIMEDIFF",
                    Long.class,
                    new TimeUnitExpression(null, String.class, "MILLISECOND"),
                    participantRoot.<Date>get("endTime"),
                    participantRoot.<Date>get("startTime")
            )
    );

TIMEDIFF return 日期时间作为结果,因此不能转换为 Long 或 double,原始结果中的 Sql 对象是 DateTime,refer this。 我可以通过使用函数从日期时间获取分钟来解决这个问题。但我通过求和的日期时间的 UNIXTIMESTAMP 差异解决了这个问题。由于 UNIXTTIMESTAMP 总是 long 我可以将它转换为 Long 或 BigInteger