2012-01-04 69 views
6

主要實體:JPA地圖W /實體鍵和實體值

@Entity public class KeyEntity 
{ 
    @Id @GeneratedValue(strategy = GenerationType.TABLE) 
    public Long id; 

    public String handle; 

    public boolean equals(Object o) { 
     KeyEntity oke = (KeyEntity) o; 
     return handle != null ? handle.equals(oke.handle) : oke.handle == null; 
    } 

    public int hashCode() { 
     return handle != null ? handle.hashCode() : 0; 
    } 
} 

價值實體:

@Entity public class ValueEntity 
{ 
    @Id @GeneratedValue(strategy = GenerationType.TABLE) 
    public Long id; 

    @ManyToOne 
    public KeyEntity key; 

    public String value; 

    public boolean equals(Object o) { 
     ValueEntity ove = (ValueEntity) o; 
     return key != null ? key.equals(ove.key) : ove.key == null; 
    } 

    public int hashCode() { 
     return key != null ? key.hashCode() : 0; 
    } 
} 

集裝箱實體:

@Entity public class ContainerEntity 
{ 
    @Id @GeneratedValue(strategy = GenerationType.TABLE) 
    public Long id; 

    @OneToMany @MapKey(name = "key") 
    public Map<KeyEntity, ValueEntity> values = new HashMap<KeyEntity, ValueEntity>(); 
} 

主營:

KeyEntity k1 = new KeyEntity(); 
k1.handle = "k1"; 
em.persist(k1); 

KeyEntity k2 = new KeyEntity(); 
k2.handle = "k2"; 
em.persist(k2); 

ValueEntity v1 = new ValueEntity(); 
v1.key = k1; 
v1.value = "v1"; 
em.persist(v1); 

ValueEntity v2 = new ValueEntity(); 
v2.key = k2; 
v2.value = "v2"; 
em.persist(v2); 

ContainerEntity ce = new ContainerEntity(); 
ce.values.put(k1, v1); 
ce.values.put(k2, v2); 
em.persist(ce); 

// display number of values 
System.out.println(ce.values.size()); 

// create new transaction 
em.getTransaction().commit(); 
em.close(); 
em = emf.createEntityManager(); 
em.getTransaction().begin(); 

// find our container and inspect the number of values 
ce = em.find(ContainerEntity.class, ce.id); 
System.out.println(ce.values.size()); 

如果我將幾個鍵值對添加到ContainerEntity,然後重新加載該容器,則只會出現一個鍵值對。如果查看運行上述主函數的輸出,首先打印「2」,然後打印「1」。

我可以看到,這是因爲KeyEntity.hashCode - 插入HashMapKeyEntity.handle時是null,因此所有對將具有相同的哈希碼。 KeyEntity.id已填充在這一點上 - 如果我基於該字段的散列碼,一切都會生效。另外,如果我將密鑰更改爲String,它會及時加載到hashCode的呼叫。

如何在ContainerEntity中更改我的映射,以便KeyEntity.handle在放置在地圖內時加載,因此hashCode可以使用它嗎?

+0

我覺得這很奇怪。爲什麼處理引用不會從數據庫中觸發它的加載?我很欣賞KeyEntity正在被延遲加載,但是訪問一個字段應該喚醒它! – 2012-01-04 23:39:57

回答

3

herehere

...至於邁克指出,@MapKey才被規範旨在用於 情況地圖<基礎,實體>,不是地圖<基本,嵌入式> 。可嵌入的值的註釋是正確的 。

I.E,它的意圖是密鑰應該是一個簡單的基本類型(這意味着不是一個實體或可嵌入的)和一個實體的價值。如果該值是基本類型,則可以使用@ElementCollection

但是,你需要的是鑰匙是一個實體類型,在這種情況下,你運氣不好。如上所述,如果您將密鑰更改爲String,則一切正常,因此我會建議您執行此操作。

+0

儘管我希望有更好的解決方案,但似乎並不存在。我正在複製ValueEntity中的字符串句柄,所以我可以使用它作爲映射鍵 – rhollencamp 2012-02-06 17:29:43