Hibernate/JPA原语映射导致奇怪的左外连接
我很难实现包含基本体映射(Map)的实体的适当映射。结果SQL不是我所期望的(左外部联接),结果是在检索所述实体的列表时,应该是唯一的实体在结果中重复 以下是实体(缩写): 一些示例内容: 用户表:Hibernate/JPA原语映射导致奇怪的左外连接,hibernate,jpa,Hibernate,Jpa,我很难实现包含基本体映射(Map)的实体的适当映射。结果SQL不是我所期望的(左外部联接),结果是在检索所述实体的列表时,应该是唯一的实体在结果中重复 以下是实体(缩写): 一些示例内容: 用户表: |username | +---------+ |admin | |brett | +---------+ 元数据表: |username |meta_key |meta_value | +---------+----------+------------+ |brett |
|username |
+---------+
|admin |
|brett |
+---------+
元数据表:
|username |meta_key |meta_value |
+---------+----------+------------+
|brett |key1 |value1 |
|brett |key2 |value2 |
+---------+----------+------------+
通过上述映射,当我使用Hibernate检索ZPrincipal列表时,如下所示:
Criteria criteria = session.createCriteria(ZPrincipal.class);
List<ZPrincipal> list = criteria.list();
导致返回行:
|username9_1_ |username9_3_ |meta2_3_ |meta3_3_ |
+--------------+--------------+----------+----------+
|admin |null |null |null |
|brett |brett |key1 |value1 |
|brett |brett |key2 |value2 |
+--------------+--------------+----------+----------+
这将产生一个包含3个实体(即“问题”)的用户列表,“管理员”用户
对象和两个“brett”用户对象(相同)。两个“brett”实例确实都包含一个正确填充的映射。对于那些想知道的人,ZPrincipal类确实重写了equals(),它提供了基于用户名(与主键相同)的比较,并且
重写hashCode()并对用户名进行哈希
我们的商店从“模式优先”设计开始工作,模式在数据库意义上似乎是“正确的”。这个问题可能可以通过一个中间的映射表和user_元数据表中生成的id来解决,但是从阅读可用的JPA和Hibernate文档()来看,似乎可以只使用两个表来映射一组基本元素
映射中缺少什么?还是冬眠中的虫子?如果是这样的话,有人能想到一个映射工作吗?我在注释方面做了不少工作,但我没有任何乐趣。这是预期的行为,并有记录在案。实例是完全相同的对象(因为hibernate保证具有相同主键的相同实体在JVM中只有一个实例)。您可以在客户端执行不同的操作来删除它们。您可以阅读Hibernate常见问题解答,了解他们决定不自动执行此操作的原因 使用“FROM ZPrincipal”尝试的是告诉Hibernate不要急于获取集合,因此它必须动态加载每个实体的映射(如果您打算读取每个获取的ZPrincipal的映射条目,这可能会导致N+1选择问题)。(或者Hibernate正在发出后续查询以填充映射) 最好的方法是自己执行重复数据消除并保存一些查询 参考:
似乎已解决。我将在这里为遇到此问题的任何其他人发布答案。当我将基于条件的查询替换为:
query query=session.createQuery(“FROM ZPrincipal”);
SQL查询本身是相同的,但结果是一个正确唯一的ZPrincipal列表。嗯,这是一个Hibernate错误,作为一个例子“FROM ZPrincipal”在语义上应该等同于:Criteria=session.createCriteria(ZPrincipal.class);List-List=Criteria.List();
非常好的答案,正是我想要的。
Criteria criteria = session.createCriteria(ZPrincipal.class);
List<ZPrincipal> list = criteria.list();
select this_.username as username9_1_,
metadata2_.username as username9_3_,
metadata2_.meta_value as meta2_3_,
metadata2_.meta_key as meta3_3_
from users this_
left outer join user_metadata metadata2_ on this_.username=metadata2_.username
|username9_1_ |username9_3_ |meta2_3_ |meta3_3_ |
+--------------+--------------+----------+----------+
|admin |null |null |null |
|brett |brett |key1 |value1 |
|brett |brett |key2 |value2 |
+--------------+--------------+----------+----------+