Java 语法错误,QueryDSL";“在什么情况下”;在地图上<&燃气轮机;字段,带有聚合

Java 语法错误,QueryDSL";“在什么情况下”;在地图上<&燃气轮机;字段,带有聚合,java,hibernate,exception,syntax,querydsl,Java,Hibernate,Exception,Syntax,Querydsl,我有一个event表和一个eventData表,它们通过Hibernate链接为Map 事件->映射事件数据 @OneToMany(fetch=FetchType.LAZY) @JoinColumn(name = "event_id", referencedColumnName = "event_id") @MapKey(name = "idk.key") public Map<DATA_KEY, eventData> getEventDatas() { return eve

我有一个
event
表和一个
eventData
表,它们通过Hibernate链接为
Map

事件->映射事件数据

@OneToMany(fetch=FetchType.LAZY)
@JoinColumn(name = "event_id", referencedColumnName = "event_id")
@MapKey(name = "idk.key")
public Map<DATA_KEY, eventData> getEventDatas() {
    return eventDatas;
}
此查询返回错误:

org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: with near line 2, column 73 
[select event.date, count(event), case when event_eventDatas_0.valeurInt = ?1 then 'OK' else 'FAIL' end
from event.eventDatas as event_eventDatas_0 with key(event_eventDatas_0) = ?2, entitystat.event event
  left join event.eventDatas
group by event.date, case when event.eventDatas.get(?2).valeurInt = ?1 then 'OK' else 'FAIL' end
order by event.date]
    at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:91)
    at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:109)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:304)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:203)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:158)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:131)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:93)
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:167)
    at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:301)
    at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:236)
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1836)
    at com.querydsl.jpa.hibernate.DefaultSessionHolder.createQuery(DefaultSessionHolder.java:36)
    at com.querydsl.jpa.hibernate.AbstractHibernateQuery.createQuery(AbstractHibernateQuery.java:104)
    at com.querydsl.jpa.hibernate.AbstractHibernateQuery.createQuery(AbstractHibernateQuery.java:97)
    at com.querydsl.jpa.hibernate.AbstractHibernateQuery.fetch(AbstractHibernateQuery.java:174)
这是Hibernate在没有groupCase的情况下生成的SQL:

select event0_.date as col_0_0_, count(event0_.event_id) as col_1_0_ 
from event event0_ 
group by event0_.date
order by event0_.date

在异常中,它显示了sql查询是如何执行的

选择
事件日期,
计数(事件),
当event\u eventDatas\u 0.valeurInt=?1时,则“OK”或“FAIL”结束
来自
event.eventDatas作为event\u eventDatas\u 0使用键(event\u eventDatas\u 0)=?2,entitystat.event event左连接event.eventDatas
按event.date、event.eventDatas.get(?2).valeurInt=?1分组,然后“确定”或“失败”结束

订购依据事件日期

选择不应包含任何与投影相关的表达式

以上group by的sql应该是
group by event.date,alisaName

适合您案例的sql语句:
选择
事件日期,
计数(事件),
当event\u eventDatas\u 0.valeurInt=?1时,则“OK”或“FAIL”结束,作为别名 来自
event.eventDatas作为event\u eventDatas\u 0使用键(event\u eventDatas\u 0)=?2,entitystat.event event左连接event.eventDatas
按event.date、别名分组

订购依据事件日期

我还没有测试下面的代码,但假设这样可以修复它(添加别名是修复它的正确方法)

final QEvent event=QEvent.event;
最终QEventData eventData=QEventData.eventData;
字符串alias=“alias”;
表达式groupCase=
event.eventDatas.get(DATA\u KEY.CODE).valueInt
。当(202)。然后(“确定”)
.否则(“失败”)。作为(别名);
构造函数表达式构造函数=
构造函数(StatDto.class、event.date、event.count()、groupCase);
query.select(构造函数)
.来自(事件)
.leftJoin(event.eventDatas、eventData)
.groupBy(event.date,别名)
.orderBy(event.date.asc());
返回query.fetch();

读了你的问题,我得出了与你相同的结论:

  • 问题很明显来自于,我不知道如何消除它
使用Hibernate可能根本不可能,我最好的猜测是,当在查询的投影中使用CASE-when表达式时,它无法预测应该使用什么值来创建新对象

您可以通过更改查询投影的构造函数来引入EventData键值,然后在StatDto构造函数中应用上一个CASE WHEN逻辑来解决此问题,如下所示:

首先,被注释为@QueryProjection的构造函数:

class StatDto {

  private Date eventDate;
  private int eventCount;
  private String eventDataStatus;

  @QueryProjection
  public StatDto(Date eventDate, int eventCount, int eventDataKey){
     this.eventDate = eventDate;
     this.eventCount = eventCount;
     if (eventDataKey == 202) {
        this.eventDataStatus = "OK";
     } else {
        this.eventDataStatus = "FAIL";
     }
  }

}
查询投影构造函数:

query.from(event) 
    .leftJoin(event.eventDatas) 
    .groupBy(event.date, groupCase) 
    .orderBy(event.date.asc())
    .list(ConstructorExpression.create(StatDto.class, event.date, event.count(), event.eventDatas.get(DATA_KEY.CODE).valueInt));
注意:我不知道上述方法是否与此完全相同,如果它与显示的代码不兼容,请尝试使用给定的想法更改代码。


等待您的反馈,祝您好运

谢谢你的回答。我根据你的例子测试了各种备选方案,但运气不好。错误仍然存在。意外标记:在第2行附近,第77列[选择日期格式(event.datetime,%Y-%m-%d%H:00'),计数(event),(case-when(event\u-eventData\u 0.valeurInt=?1)然后“OK”或“1fail”结束)作为来自event.eventData的测试项(event\u-eventData\u 0)=?2,事件事件左连接event.eventData内部连接event.logmovement为m,带有m.logNoeudOrigine.idk.type=?3,其中event.type=?4和event.datetime介于?5和?6之间,按日期分组(event.datetime,%Y-%m-%d%H:00'),testAlias order by event.datetime desc]我认为问题来自于
from event.eventData as event\u eventData\u 0,key(event\u eventData\u 0)=?2,event event
。这是自动添加的,但感觉是错误的。我也有同样的感觉,它不应该是
事件事件
,从先前的帖子异常来看,它应该是
entitystat.event event left join event.eventDatas
。您是否更改了您的
查询。选择(构造函数)。从(事件)…....
右侧,即
entitystat.event事件
。由于字符数有限,我不得不缩减注释,而且我有点激进。您能提供生成的SQL而不使用groupCase吗?谢谢@Bonifacio我在问题的末尾添加了SQL。问题是否已解决。否,问题仍在继续。没有人能找到正确的方法来实现这一点。谢谢你的回答。我试了一下
@QueryProjection
很方便,但不能解决问题(从现在起我将使用它)。遗憾的是,如果我直接接收到dataKey值,那么聚合将不正确,它将创建许多“fail”DTO,而不是只有一个具有总和的DTO。
final QEvent event = QEvent.event;
final QEventData eventData = QEventData.eventData;

String alias="alias";

Expression<String> groupCase = 
event.eventDatas.get(DATA_KEY.CODE).valueInt 
.when(202).then("OK") 
.otherwise("FAIL").as(alias);

ConstructorExpression<StatDto> constructor = 
Projections.constructor(StatDto.class, event.date, event.count(), groupCase);

query.select(constructor) 
.from(event) 
.leftJoin(event.eventDatas,eventData) 
.groupBy(event.date, alias) 
.orderBy(event.date.asc());

return query.fetch();
class StatDto {

  private Date eventDate;
  private int eventCount;
  private String eventDataStatus;

  @QueryProjection
  public StatDto(Date eventDate, int eventCount, int eventDataKey){
     this.eventDate = eventDate;
     this.eventCount = eventCount;
     if (eventDataKey == 202) {
        this.eventDataStatus = "OK";
     } else {
        this.eventDataStatus = "FAIL";
     }
  }

}
query.from(event) 
    .leftJoin(event.eventDatas) 
    .groupBy(event.date, groupCase) 
    .orderBy(event.date.asc())
    .list(ConstructorExpression.create(StatDto.class, event.date, event.count(), event.eventDatas.get(DATA_KEY.CODE).valueInt));