微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决JPA CriteriaQuery 无法为日期差异总和找到合适的构造函数

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

这是异常信息

获取数据时出现异常 (/periodicReport/userReport): org.hibernate.hql.internal.ast.QuerySyntaxException:无法定位 类上适当的构造函数 [com.analytics.entity.projections.UserParticipantCountAndDurationImpl]。 预期参数为:java.util.UUID、long、java.util.Date [选择 新的 com.analytics.entity.projections.UserParticipantCountAndDurationImpl(生成的Alias0.userID, 计数(不同的生成别名0.userID),总和(函数('TIMEDIFF', generatealias0.endTime,generatedalias0.startTime))) 来自 com.analytics.entity.ConferenceParticipant 作为 generatealias0 group bygeneratedalias0.userID order by :param0 desc]

我期望总和为 Long 并且我在标准查询中指定了它。 我不知道日期在哪里定义

为建造者的 snipet

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)
    ));

有问题的课程

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。