Java Hibernate条件查询在生成的SQL中以错误的顺序列出表
我有一个使用多个联接的条件查询,生成的SQL无序地列出了表,因此ON子句引用了一个尚未声明的表 为了重现这个问题,我创建了一个包含三个表的小数据模型:Bill、Event和一个连接表BillEvent(我在问题的末尾列出了一个带有实体定义的可运行JUnit测试)。以下条件查询因语法错误而失败,因为Java Hibernate条件查询在生成的SQL中以错误的顺序列出表,java,hibernate,hibernate-5.x,Java,Hibernate,Hibernate 5.x,我有一个使用多个联接的条件查询,生成的SQL无序地列出了表,因此ON子句引用了一个尚未声明的表 为了重现这个问题,我创建了一个包含三个表的小数据模型:Bill、Event和一个连接表BillEvent(我在问题的末尾列出了一个带有实体定义的可运行JUnit测试)。以下条件查询因语法错误而失败,因为event1是在引用后声明的如何重写此查询,以便以正确的顺序声明表? // Get the most recent BillEvent for a bill final Criteria criteri
event1
是在引用后声明的如何重写此查询,以便以正确的顺序声明表?
// Get the most recent BillEvent for a bill
final Criteria criteria = session.createCriteria(BillEvent.class, "be1")
.createCriteria("event", "event1")
.createCriteria("be1.bill")
.add(Restrictions.eq("id", billId))
.createCriteria("billEvents", "be2")
.createCriteria("event", "event2", JoinType.LEFT_OUTER_JOIN,
Restrictions.ltProperty("event1.time", "time"))
.add(Restrictions.isNull("event2.id"));
错误:
Caused by: org.h2.jdbc.JdbcSQLException: Column "EVENT1X1_.TIME" not found; SQL statement:
select
this_.id as id1_1_4_,
this_.billId as billId3_1_4_,
this_.eventId as eventId4_1_4_,
this_.note as note2_1_4_,
hibernatej2_.id as id1_0_0_,
hibernatej2_.label as label2_0_0_,
be2x3_.id as id1_1_1_,
be2x3_.billId as billId3_1_1_,
be2x3_.eventId as eventId4_1_1_,
be2x3_.note as note2_1_1_,
event2x4_.id as id1_2_2_,
event2x4_.time as time2_2_2_,
event1x1_.id as id1_2_3_,
event1x1_.time as time2_2_3_
from
test.billEvent this_
inner join test.bill hibernatej2_ on this_.billId=hibernatej2_.id
inner join test.billEvent be2x3_ on hibernatej2_.id=be2x3_.billId
left outer join test.event event2x4_
on be2x3_.eventId=event2x4_.id
and ( event1x1_.time<event2x4_.time )
inner join test.event event1x1_ on this_.eventId=event1x1_.id
where
hibernatej2_.id=?
and event2x4_.id is null
生成的订单将是
from root
inner join root.a on (... and root.z.prop = root.a.prop)
inner join root.z
inner join root.z.a
inner join root.z.b
将
BillEvent.bill
重命名为BillEvent.zBill
(或事件
之后的任何字母顺序)可修复此查询中的语法错误。但是,这是不可伸缩的:如果您想从连接表的另一端进行查询,该查询将失败,因为它现在按字母顺序排列不正确。使用条件时,hibernate实际上以深度优先搜索方式遍历实体树,根据配置中的字段定义构建联接。在您的例子中,BillEvent首先遍历bill,然后遍历bill类的子字段。因此,基本上,它在创建来自bill关联的所有联接之后,创建事件实体联接。您可以在hbm.xml中定义顺序,但正如您所提到的,它的可伸缩性不强
因此,这里至少有两个选项:
尝试使用“createAlias”而不是“createCriteria”@richarbernal,这也不起作用。至少不是在derby:memory db上使用提供的测试用例。我想您对该特定查询的解决方案不感兴趣,而是对通用解决方案感兴趣?@flo-是的,我可以在HQL中一次性编写这个,或者使用JOOQ,但我更喜欢Criteria,因为我有很多类似的查询要转换,而且看起来不那么脆弱。@Sam Ok:-)我用Criteria解决了这个问题,但我认为这不是一个通用模式:可能有帮助:
final Criteria Criteria=session.createCriteria(BillEvent.class,“be”).createAlias(“event”,event”).createCriteria(“bill”).add(Restrictions.eq(“id”,billId)).addOrder(Order.desc(“event.time”);
from root
inner join root.a on (... and root.z.prop = root.a.prop)
inner join root.z
inner join root.z.a
inner join root.z.b
final Criteria criteria = session.createCriteria(Event.class, "event1")
.createCriteria("event1.billEvents", "be1")
.createCriteria("be1.bill", "bill1")
.createCriteria("bill1.billEvents", "be2")
.createCriteria("be2.event", "event2", JoinType.LEFT_OUTER_JOIN,
Restrictions.ltProperty("event1.time", "event2.time"))
.add(Restrictions.eq("be1.id", billId))
.add(Restrictions.isNull("event2.id"))
.setProjection(Projections.projectionList()
.add(Projections.property("be1.event"), "event")
.add(Projections.property("be1.note"), "note"))
.setResultTransformer(Transformers.aliasToBean(BillEvent.class));