Hibernate 6 NativeQuery查询同类型多实体仅返回首个实体问题
Hibernate 6 NativeQuery 查询同类型多实体重复返回首个实体的解决方法
问题现象
从Hibernate 5迁移至Hibernate 6后,使用NativeQuery查询同类型的多个实体时,返回结果中所有实体均与首个实体重复。例如执行以下代码:
List<Object[]> res = sess.createSQLQuery("SELECT {cat.*}, {m.*} FROM CATS c, CATS m WHERE c.MOTHER_ID = m.ID") .addEntity("cat", Cat.class) .addEntity("mother", Cat.class) .list();
Hibernate 5中会返回两个不同的Cat实体(子猫和母猫),但Hibernate 6中返回的是两个完全相同的子猫实体。同时Hibernate 6官方文档已移除同类型多实体查询的示例,替换为不同实体类型的查询示例。
原因分析
Hibernate 6对NativeQuery的实体解析逻辑进行了调整:当查询同类型的多个实体时,默认会复用第一个实体的映射规则,导致后续同类型实体无法被正确解析为独立对象。
解决方案
方案1:使用@SqlResultSetMapping显式定义结果映射
通过注解定义明确的结果集映射,区分同类型的不同实体:
@SqlResultSetMapping( name = "CatAndMotherMapping", entities = { @EntityResult(entityClass = Cat.class, name = "cat"), @EntityResult(entityClass = Cat.class, name = "mother") } )
查询时指定该映射:
List<Object[]> res = sess.createNativeQuery( "SELECT {cat.*}, {mother.*} FROM CATS cat, CATS mother WHERE cat.MOTHER_ID = mother.ID", "CatAndMotherMapping" ).list();
方案2:使用Tuple接收结果并通过别名获取实体
通过Tuple类型接收结果,然后根据表别名获取对应的实体对象:
List<Tuple> tuples = sess.createNativeQuery( "SELECT c.*, m.* FROM CATS c, CATS m WHERE c.MOTHER_ID = m.ID", Tuple.class ) .addEntity("c", Cat.class) .addEntity("m", Cat.class) .list(); // 遍历处理结果 for (Tuple tuple : tuples) { Cat cat = (Cat) tuple.get("c"); Cat mother = (Cat) tuple.get("m"); // 业务逻辑处理 }
方案3:显式指定列别名与实体的映射
修改SQL语句,为每个表的列添加专属别名,确保Hibernate能区分不同实体的字段:
List<Object[]> res = sess.createSQLQuery( "SELECT c.id AS cat_id, c.name AS cat_name, m.id AS mother_id, m.name AS mother_name " + "FROM CATS c, CATS m WHERE c.MOTHER_ID = m.ID" ) .addEntity("cat", Cat.class) .addEntity("mother", Cat.class) .list();
这种方式适合字段较少的场景,字段较多时建议使用前两种方案。
内容的提问来源于stack exchange,提问作者Ivan Merkish
相关产品推荐
相关产品推荐

