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
我知道这个问题看起来很相似,但我认为情况不同
这是异常消息
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