Criteria.DISTINCT_ROOT_ENTITY的工作原理及等效SQL写法是什么?
DISTINCT_ROOT_ENTITY 运行逻辑说明
DISTINCT_ROOT_ENTITY 是Hibernate的内存结果转换器,不会在生成的SQL中加入去重逻辑,所有去重操作都是在Java服务端内存中完成的。
它的去重规则非常简单:以查询定义的根实体(你这里对应MyEntity类,映射TABLEB表)的主键值作为唯一标识,只要结果集中多条行记录对应的根实体主键值相同,就只保留第一条加载的根实体实例,后续重复条目会被直接丢弃。
你遇到的SQL关联查询返回2500条、但Hibernate查询返回2000条的差异,本质原因就是SQL返回的是TABLEA和TABLEB关联后的笛卡尔积行,其中有500条是重复的TABLEB实体对应的关联行,被Hibernate在内存中做了去重。
Oracle 方言下的等效原生SQL写法
你要实现和原Criteria查询完全一致的返回结果,有两种常用写法:
写法1:基于DISTINCT的简洁写法
如果TABLEB没有超大字段,直接对TABLEB全字段去重即可,和Hibernate去重逻辑完全对齐:
SELECT DISTINCT b.* FROM TABLEA a INNER JOIN TABLEB b ON b.fk = a.sysid WHERE a.property1 = someValue AND a.property2 = someOtherValue;
写法2:基于窗口函数的高性能写法
如果TABLEB存在大字段,用ROW_NUMBER()窗口函数按主键分组去重,性能更优:
SELECT * FROM ( SELECT b.*, ROW_NUMBER() OVER (PARTITION BY b.【TABLEB主键字段名】 ORDER BY 1) AS rn FROM TABLEA a INNER JOIN TABLEB b ON b.fk = a.sysid WHERE a.property1 = someValue AND a.property2 = someOtherValue ) temp WHERE temp.rn = 1;
常见理解偏差说明
你写的关联查询逻辑和原Criteria的SQL生成逻辑基本等效,唯一的差异就是原Criteria查询不会在SQL层面加去重,而是在内存中做根实体去重。如果你的业务场景中存在同一个TABLEB实体关联多个符合条件的TABLEA记录的情况,直接查关联行的COUNT(*)必然会大于TABLEA的符合条件行数,属于正常现象。
内容的提问来源于stack exchange,提问作者Eskir
相关产品推荐
相关产品推荐

