0

我有两个实体DeptEmp(实际情况已更改并最小化)。它们之间存在 1:n 的关联,即属性Dept.empList,并Emp.dept与各自的注释一起存在。我想使用本机 SQL 查询来获取List<Dept>其元素是不同的并empList热切地初始化集合。

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]>实例DeptEmp按此顺序) 。Dept.empList没关系。

为了获得不同Dept的 s,我认为设置变压器DISTINCT_ROOT_ENTITY(取消注释该行)就足够了。不幸的是,DistinctRootEntityResultTransformer它基于RootEntityResultTransformer将元组中的最后一个元素视为根实体(它是硬连线的)。由于实体的顺序是由addEntity,addJoin调用的序列决定的,因此转换器错误地将Emp其视为根实体并返回包含所有Emps 的所有Depts 的列表。

有没有什么干净的方法可以让 Hibernate 将其识别Dept为根实体,即使它不是实体列表中的最后一个?

注 1:我尝试将 order 切换为.addJoin("e", "d.empList").addEntity("d", Dept.class). d.empList由于需要d定义,因此不起作用。HibernateSystemException : Could not determine fetch owner在 Hibernate 内部(org.hibernate.loader.Loader)的某个地方失败。

注 2:我试图将 order 定义为.addEntity("e", Emp.class).addJoin("d", "e.dept"). 这看似有效,但该关联实际上仅从“多”方填充。因此,在请求之前,该集合Dept.empList是一些未初始化的代理,它调用显式 SQL 查询,因此在我的查询中不使用连接。

注 3:寻找硬连线索引的自定义变压器有效:

        .setResultTransformer(new BasicTransformerAdapter() {
            public Object transformTuple(Object[] tuple, String[] aliases) {
                return tuple[0];
            }
            public List transformList(List list) {
                return DistinctResultTransformer.INSTANCE.transformList( list );
            }
        })

虽然我很犹豫接受这么简单的任务可能有这么复杂的解决方案。

Hibernate 版本:3.6.10(我知道 - 遗留项目 :-) 虽然我查看了最新版本的源代码,但似乎关键点没有不同)。

4

1 回答 1

0

终于找到了https://stackoverflow.com/a/17210746/653539 - 重复调用.addEntity以在列表末尾强制根实体:

    .addEntity("d", Dept.class)
    .addJoin("e", "d.empList")
    .addEntity("d", Dept.class)

它仍然是解决方法,但比我的更干净 - 基于 36 次投票 - 它似乎是惯用的解决方案。

于 2020-06-24T13:19:20.557 回答