マップをデータベースに保存することになっている次のコードがあります。問題は、エンティティとその関係を保存している間、マップのキー値をサイレントに破棄することです。エラーは発生せず、データベースは代わりにNULLを取得します。
コード:
package com.tester;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.MapKey;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import lombok.Data;
import lombok.ToString;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
public class App {
@Entity
@Table (name = "test_items")
@Data
@ToString (exclude = "parent")
public static class Item {
@Id @GeneratedValue
private Long id;
int slot;
@ManyToOne
private Item parent;
@OneToMany (cascade = CascadeType.ALL, mappedBy = "parent")
@MapKey (name = "slot")
Map<Integer, Item> children;
}
private static SessionFactory buildSessionFactory() {
try {
return new AnnotationConfiguration().configure().buildSessionFactory();
} catch (final Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static void main(final String[] args) {
final SessionFactory sf = buildSessionFactory();
final Session session = sf.openSession();
session.beginTransaction();
final Item item100 = new Item();
final Item item110 = new Item();
session.save(item100);
session.save(item110);
session.flush();
item110.setParent(item100);
final HashMap<Integer, Item> children = new HashMap<Integer, Item>();
children.put(3, item110);
item100.setChildren(children);
session.saveOrUpdate(item100);
session.saveOrUpdate(item110);
session.getTransaction().commit();
session.close();
}
}
上記の後に予想されるデータベースの結果:
id slot parent_id
1 0 NULL
2 3 1 [->]
実結果:
id slot parent_id
1 0 NULL
2 0 1 [->]
ご覧のとおり、Hibernateがキーの列を作成した場合でも、キーにはNULLが入力され、からの情報「3」children.put(3, item110);
はデータベースにまったく保持されません。それは完全に失われます。
アイデア?
注:私も試し@MapKeyClass (Integer.class)
ましたが、成功しませんでした。
編集:問題の3は、他のものを参照することを意図したものではなく、他のフィールド/列への参照でもありません。これは任意の値であり、この特定のコンテキストでは、多数のスロットを持つコンテナ内のアイテムのインデックスを定義する必要があります。しかし、私が気にかけていることはすべて、それを「abcdefg」に置き換えることができます(もちろん、整数ではなく文字列を使用するようにマップを変更したと仮定します)。