我很难实现包含基元映射的实体的映射(Map < String,String>)。结果SQL并非我所期望的(左外连接),结果是,当检索所述实体的列表时,应该是唯一的实体在结果中被复制。Hibernate/JPA Map of Primitives导致奇怪的左外连接
这里是为实体(简称):
@Entity(name = "ZPrincipal")
@Table(name = "users")
public class ZPrincipal implements Principal, Serializable {
@Id
@Column(name = "username")
private String username;
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "user_metadata", joinColumns = { @JoinColumn(name = "username") })
@MapKeyColumn(name = "meta_key")
@Column(name = "meta_value", nullable = false)
private Map<String, String> metadata;
}
正如你可以看到,有一个用户类(ZPrincipal),其中包含一个地图。我的表是这样的(再次,从缩写某些领域 '用户',如电子邮件,密码等):
CREATE TABLE users (
username VARCHAR(60) NOT NULL,
PRIMARY KEY (username)
);
CREATE TABLE user_metadata (
username VARCHAR(60) NOT NULL,
meta_key VARCHAR(255) NOT NULL,
meta_value VARCHAR(1024) NOT NULL,
CONSTRAINT user_meta_fk FOREIGN KEY (username) REFERENCES users (username),
PRIMARY KEY (username, meta_key)
);
一些示例内容:
用户表:
|username |
+---------+
|admin |
|brett |
+---------+
元表:
|username |meta_key |meta_value |
+---------+----------+------------+
|brett |key1 |value1 |
|brett |key2 |value2 |
+---------+----------+------------+
通过上述映射,当我使用Hibernate检索ZPrincipals列表,像这样:
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 |
+--------------+--------------+----------+----------+
这导致含有3实体的用户的列表(即“问题”),“admin”用户对象和两个“brett”用户对象(相同)。这两个“brett”实例确实包含一个正确填充的Map。对于那些想知道的,ZPrincipal类确实覆盖equals(),它提供了一个基于用户名(与主键相同)的比较,并且 覆盖hashCode()也对用户名进行散列。
我们的商店从“架构第一”设计开始工作,架构在数据库意义上看起来“正确”。可能这个问题可以通过插入映射表和生成的id在user_metadata表中解决,但是通过阅读可用的JPA和Hibernate文档(),似乎应该可能仅使用两个表来映射一组基本元素。
映射中缺少什么?或者它是Hibernate中的错误?如果是这样,任何人都可以想到映射解决方法?我对这些注释进行了很少的无聊。
看似解决了。我会在这里为所有遇到此问题的人发布答案。当我将基于标准的查询替换为: Query query = session.createQuery(“FROM ZPrincipal”);` SQL查询本身是相同的,但结果是一个正确唯一的ZPrincipals列表。恕我直言,这是一个Hibernate漏洞,因为“FROM ZPrincipal”在语义上应该等价于: `Criteria criteria = session.createCriteria(ZPrincipal.class); 列表 list = criteria.list();` –
brettw
2011-02-14 02:53:14