如何在Blaze-Persistence中结合unionAll使用select new?
带UnionAll的CriteriaBuilder映射到ObjectBuilder的解决方案
在使用包含unionAll集合操作的CriteriaBuilder查询时,尝试在endSet()后添加.selectNew(EOB)会触发报错:
modifications to a query after connecting with a set operation is not allowed
现有代码结构如下:
cb.with(ChangesCTE.class) .from(Changes.class) .bind... .where... .groupBy... .end() .from(ChangesCTE.class, "update") .innerJoinOn(entityClass, "entity") .on("update.id").onExpression("entity.id") .end() .where... .unionAll() .from(ChangesCTE.class, "update") .innerJoinOn(otherEntityClass, "otherEntity") .on("update.id").onExpression("otherEntity.id") .end() .where... .endSet() .orderByAsc... // .selectNew(EOB);
正确做法:在每个Union分支内单独指定selectNew
unionAll要求所有参与合并的子查询返回的字段数量、类型完全匹配,因此需要在每个子查询的末尾添加selectNew(EOB),确保每个分支都输出EOB类型的结构,合并后即可直接得到目标对象集合。
修改后的代码示例:
cb.with(ChangesCTE.class) .from(Changes.class) .bind... .where... .groupBy... .end() .from(ChangesCTE.class, "update") .innerJoinOn(entityClass, "entity") .on("update.id").onExpression("entity.id") .end() .where... .selectNew(EOB) // 第一个分支添加selectNew,映射EOB属性 .set("property1", "update.field1") .set("property2", "entity.field2") .endSelect() .unionAll() .from(ChangesCTE.class, "update") .innerJoinOn(otherEntityClass, "otherEntity") .on("update.id").onExpression("otherEntity.id") .end() .where... .selectNew(EOB) // 第二个分支同步添加selectNew,属性映射需与第一个分支完全一致 .set("property1", "update.field1") .set("property2", "otherEntity.field2") .endSelect() .endSet() .orderByAsc...
关键说明
- 两个
unionAll分支的selectNew必须映射完全相同的EOB属性,保证字段数量、类型一致,否则会触发union结构不匹配的错误。 - 不需要在
endSet()后再添加任何select操作,合并后的结果会直接是EOB类型的数据集。
内容的提问来源于stack exchange,提问作者fishi
相关产品推荐
相关产品推荐

