2012-01-04 12 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に複数のキーと値のペアを追加してから、そのコンテナをリロードすると、1つのキーと値のペアのみが存在します。上記のメイン関数を実行した結果を見ると、最初に '2'が出力され、その後に '1'が出力されます。私はこれが原因KeyEntity.hashCodeであることがわかります

- HashMapKeyEntity.handleに挿入するときは、そのすべてのペアは、同じハッシュコードを持つことになり、nullです。この時点でKeyEntity.idが入力されます。このフィールドのハッシュコードを基にすれば、すべてが機能します。また、Stringにキーを変更した場合は、hashCodeへの呼び出しに間に合います。

ContainerEntityでマッピングを変更すると、KeyEntity.handleがマップの中に置かれたときにロードされるので、hashCodeはそれを使用できますか?

+0

私はこれをかなり奇妙に感じます。なぜ、処理するリファレンスがデータベースからのロードをトリガーしないのですか?私はKeyEntityが遅れてロードされていることを感謝しますが、フィールドへのアクセスは目を覚ます必要があります! –

答えて

3

参照herehere

マイクが指摘するように、@MapKeyは、基本的な、エンティティ>、ない、組み込み>地図<基本のため ケースマップ<の仕様により意図していました... 。埋め込み可能な値の正しい 注釈は、です。

I.Eでは、キーは単純な基本型(エンティティまたは埋め込み可能でないことを意味します)とエンティティの値であることを意図しています。値が基本タイプの場合は@ElementCollectionとなります。

しかし、必要なのは、キーがエンティティタイプであり、この場合、あなたは不運です。

すでに述べたように、キーをStringに変更した場合はすべて問題ありませんので、これをお勧めします。

+0

私はより良い解決策を望んでいた限り、1つあるとは思われません。 ValueEntityでStringハンドルを複製しているので、マップキーとして使用できます – rhollencamp

関連する問題