我对querydsl有点新,目前正致力于我们的任务 想要在不使用生成的Q-class的情况下访问OneToMany相关表,并在其上执行子查询。我们正在使用 QueryDsl 3.7.4 。在此示例中,我们在 date 列上获得了一个简单的 max -Statement。
我试图实现的陈述应该是这样的:
select person
from person p
left join p.instructions as i
where i.validUntil = (
select max(i.validUntil) from instruction i2 where i2.person = p
)
人员实体:
@OneToMany(cascade = {..},mappedBy = "person")
private Set<Instruction> instructions = new HashSet<>();
指令实体:
@Entity(name = "instruction")
public class Instruction {
...
@Column(name = "validuntil", nullable = true)
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
private LocalDate validUntil;
...
}
变量:
query: select baseEntity from person baseEntity [..]
pathBuilder: baseEntity
entityPath: baseEntity.instructions
entityClazz: java.util.Set
propName: validUntil
到目前为止,我尝试了不同的解决方案:
if (entityClazz.isAssignableFrom(Set.class)) {
CollectionPath<Object, PathBuilder<Object>> collection =
pathBuilder.getCollection(entityName, entityClazz);
query.leftJoin(collection.any());
if ("date".equals(columnModel.getType())) {
DateSubQuery<LocalDate> sub = new JPASubQuery().from(entityPath).where(collection.any().eq(pathBuilder))
.unique(collection.any().getDate(propName, LocalDate.class).max());
query.where(collection.any().getDate(propName, LocalDate.class).eq(sub));
}
}
导致 IllegalArgumentException:Undeclared path&quot; baseEntity_instructions_64058&#39;。将此路径添加为查询的源,以便能够引用它。
我有点理解,因为我并没有真正宣布&#39; baseEntity_instructions_64058&#39;任何地方。但是我该怎么做呢?
然后我尝试用entityPath替换collection.any()语句:
DateSubQuery<LocalDate> sub =
new JPASubQuery().from(entityPath).where(entityPath.eq(pathBuilder))
.unique(entityPath.getDate(propName, LocalDate.class).max());
query.where(entityPath.getDate(propName, LocalDate.class).eq(sub));
生成的查询对我来说不错:
select baseEntity
from Person baseEntity
...
left join baseEntity.instructions
where baseEntity.instructions.validUntil = (select max(baseEntity.instructions.validUntil)
from baseEntity.instructions
where baseEntity.instructions = ?1)
..但使用以下消息抛出 org.hibernate.QueryException :
使用元素属性引用[validUntil]非法尝试取消引用集合[person0_.auto_id.instructions]
另一种尝试,别名如下:
PathBuilder<IFlattenable> alias = new PathBuilder<IFlattenable>(entityClazz,entityPath.as("subEntity").toString());
query.leftJoin(alias);
DateSubQuery<LocalDate> sub = new JPASubQuery().from(entityPath).where(alias.eq(entityPath))
.unique(alias.getDate(propName, LocalDate.class).max());
query.where(alias.getDate(propName, LocalDate.class).eq(sub));
生成以下查询:
select baseEntity
from person baseEntity
...
left join Set baseEntity.instructions as subEntity
where baseEntity.instructions as subEntity.validUntil = (select max(baseEntity.instructions as subEntity.validUntil)
from baseEntity.instructions
where baseEntity.instructions as subEntity = baseEntity.instructions)
最终以 antlr.NoViableAltException:意外令牌:设置。我不明白为什么它会增加&#34; Set&#34;到查询。我也希望&#34; baseEntity.instructions为subEntity&#34;只使用一次(在实际连接时),之后只使用别名&#34; subEntity&#34;供参考。
我已经坚持了一段时间了,阅读了很多stackoverflow和github发布的帖子,尝试了很多各种&#34;解决方案&#34;的组合。有人能帮我解决这个问题吗?
先谢谢,我会给你买一杯饮料:)