休眠 5.6.15.最终版
我有2个具有一对一关系的实体,都有审核字段“createdBy”、“modifiedBy”、“createdDate”、“modifiedDate”。
class EntityA {
...
EntityB myEntityB;
String createdBy;
Timestamp createdDate;
String modifiedBy;
Timestamp modifiedDate;
}
class EntityB {
...
String createdBy;
Timestamp createdDate;
String modifiedBy;
Timestamp modifiedDate;
}
我写了一个本机查询
List<Object[]> rows = currentSession().createNativeQuery("SELECT o.*, d.* FROM mytable1 o JOIN mytable2 d ON ...")
.addEntity("o", EntityA.class)
.addJoin("d", "o.myEntityB")
.getResultList();
但是,作为响应返回的 EntityB 实例包含审核字段的无效值 - 它们只是复制 EntityA 实例中审核字段的值。
Hibernate 5 在从查询映射到实体时依赖于
java.sql.ResultSet
和列名称
但是,
java.sql.ResultSet
在docs中指定:
当使用列名和多个列调用 getter 方法时 具有相同的名称,则第一个匹配列的值将是 回来了
在 Hibernate 6 中这个问题应该已经得到解决,因为它依赖于列索引而不是名称。
Hibernate 5 中的解决方法可能是选择两次具有相同名称的列并手动设置它们。对于非本机查询,Hibernate 会自行执行此操作(请参阅Hibernate 选择相同的列两次。为什么以及目的是什么?)。
解决方法示例:
List<Object[]> rows = currentSession().createNativeQuery("""
SELECT o.*, d.*, d.created_by as d_created_by, d.created_date as d_created_date, ...
FROM mytable1 o JOIN mytable2 d ON ...
""")
.addEntity("o", EntityA.class)
.addJoin("d", "o.myEntityB")
.addScalar("d_created_by")
.addScalar("d_created_date")
...
.getResultList();
for (Object[] row : rows) {
((EntityA) row[0]).getMyEntityB().setCreatedBy((String) row[1]);
((EntityA) row[0]).getMyEntityB().setCreatedDate((Timestamp) row[2]);
...
}