我很難實現包含基元映射的實體的映射(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