问题描述
我有两个实体 Dept
和 Emp
(实际情况已更改并最小化).它们之间存在1:n的关联,即属性 Dept.empList
和 Emp.dept
存在各自的注释.我想获取 List< Dept>
,其元素是不同的,并且使用本机SQL查询对集合 empList
进行了初始化.
I have two entities Dept
and Emp
(real case changed and minimized). There is 1:n association between them, i.e. properties Dept.empList
and Emp.dept
exist with respective annotations. I want to get List<Dept>
whose elements are distinct and have collection empList
eagerly initialized, using native SQL query.
session.createSQLQuery("select {d.*}, {e.*} from dept d join emp e on d.id = e.dept_id")
.addEntity("d", Dept.class)
.addJoin("e", "d.empList")
//.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.list();
此查询返回 List< Object [2]>
和数组中的 Dept
, Emp
实例(按顺序),并且字段 Dept.empList
正确初始化.没关系.
This query returns List<Object[2]>
with instances of Dept
, Emp
(in that order) in the array and field Dept.empList
properly initialized. That's ok.
要获得独特的 Dept
,我认为设置转换器 DISTINCT_ROOT_ENTITY
(取消注释该行)就足够了.不幸的是, DistinctRootEntityResultTransformer
是基于 RootEntityResultTransformer
的,后者将元组中的最后一个元素视为根实体(它是硬连线的).由于实体的顺序是由 addEntity
, addJoin
调用的顺序确定的,所以转换器错误地将 Emp
视为根实体,并返回所有 Dept 的code> Emp .
To get distinct Dept
s, I thought setting transformer DISTINCT_ROOT_ENTITY
(uncommenting the line) would be enough. Unfortunately, the DistinctRootEntityResultTransformer
is based on RootEntityResultTransformer
which treats the last element in tuple as root entity (it's hardwired). Since the order of entities is determined by sequence of addEntity
, addJoin
calls, the transformer mistakenly treats Emp
as root entity and returns list with all Emp
s of all Dept
s.
是否有任何干净的方法可以使Hibernate将 Dept
识别为根实体,即使它不在实体列表中也不是最后一个?
Is there any clean way how to make Hibernate recognized the Dept
as root entity, even though it is not last in entity list?
注释1:我试图将顺序切换为 .addJoin("e","d.empList").addEntity("d",Dept.class)
.由于 d.empList
需要定义 d
,因此无法使用.出现 HibernateSystemException失败:无法确定Hibernate内部组件(
. org.hibernate.loader.Loader
)中某个地方的获取所有者
Note 1: I tried to switch order to .addJoin("e", "d.empList").addEntity("d", Dept.class)
. Does not work since d.empList
requires d
defined. Fails on HibernateSystemException : Could not determine fetch owner
somewhere in Hibernate internals (org.hibernate.loader.Loader
).
注释2:我试图将顺序定义为 .addEntity("e",Emp.class).addJoin("d","e.dept")
.这看似有效,但是实际上仅从许多"列表中填充关联.边.因此,集合 Dept.empList
是一些未初始化的代理,直到被请求为止,该代理将调用显式SQL查询,因此不会在我的查询中使用连接.
Note 2: I tried to define order as .addEntity("e", Emp.class).addJoin("d", "e.dept")
. This seemingly works but the association is actually filled only from the "many" side. Hence the collection Dept.empList
is some uninitialized proxy until requested, which invokes explicit SQL query and thus does not utilize the join in my query.
注释3:寻找硬接线索引的自定义转换器有效:
Note 3: The custom transformer looking for hard-wired index works:
.setResultTransformer(new BasicTransformerAdapter() {
public Object transformTuple(Object[] tuple, String[] aliases) {
return tuple[0];
}
public List transformList(List list) {
return DistinctResultTransformer.INSTANCE.transformList( list );
}
})
尽管我不愿接受这样简单的任务可能会有如此复杂的解决方案.
though I'm hesitant to accept such easy task could have such complicated solution.
休眠版本:3.6.10(我知道-遗留项目:-),尽管我调查了最新版本的源代码,但关键点似乎没有什么不同.
Hibernate version: 3.6.10 (I know - legacy project :-) though I looked into source code of latest version and seems the key points don't differ).
推荐答案
最后找到 https://stackoverflow.com/a/17210746/653539 -重复调用 .addEntity
以将根实体强制在列表末尾:
Finally found https://stackoverflow.com/a/17210746/653539 - make duplicate call of .addEntity
to force root entity on the end of list:
.addEntity("d", Dept.class)
.addJoin("e", "d.empList")
.addEntity("d", Dept.class)
它仍然可以解决,但比我的清洁,并且-基于36个投票-似乎是惯用的解决方案.
It's still workaround but cleaner than mine and - based on 36 upvotes - it seems as idiomatic solution.
这篇关于Hibernate本机SQL查询-如何通过热切初始化的一对多关联获取不同的根实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!