Ich verstehe nicht das Verhalten von Hibernate beim Mapping einer bidirektionalen Liste. Die SQL-Anweisungen, die Hibernate erzeugt, scheinen mir nicht optimal zu sein. Kann mich jemand aufklären?Mapping einer bidirektionalen Liste mit Hibernate
Das Szenario ist das folgende: Ich habe eine Eins-zu-viele-Eltern-Kind-Beziehung. Ich ordnet diese Beziehung einer bidirektionalen Liste zu.
Nach dem Hibernate Annotation Reference Guide (Kapitel: Bidirektionale Verbindung mit indexierten Sammlungen) der Abbildung sollte wie folgt aussehen:
@Entity
public class Parent {
@Id @GeneratedValue private long id;
@Version private int version;
private String name;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "parent_id", nullable=false)
@org.hibernate.annotations.IndexColumn(name = "parent_index")
List<Child> children = new ArrayList<Child>();
...
@Entity
public class Child {
@Id @GeneratedValue private Long id;
@Version private int version;
private String name;
@ManyToOne
@JoinColumn(name = "parent_id", updatable = false, insertable = false, nullable=false)
private Parent parent;
...
Aber in diesem Fall Hibernate produziert drei SQL-Anweisungen, wenn ein Elternteil mit einem Kind persistierenden:
Hibernate: insert into Parent (name, version, id) values (?, ?, ?)
Hibernate: insert into Child (name, price, version, parent_id, parent_index, id) values (?, ?, ?, ?, ?, ?)
Hibernate: update Child set parent_id=?, parent_index=? where id=?
Die dritte Anweisung scheint redundant zu sein, denn parent_id
und parent_index
scheinen bereits in der zweiten Anweisung gesetzt zu sein.
Wenn ich die Zuordnung ändern, und wiederholen Sie die Attribute 'aktualisierbar = false, einführbar = false' auf die Erklärung des @JoinColumn in der Eltern wie folgt aus:
@Entity
public class Parent {
@Id @GeneratedValue private long id;
@Version private int version;
private String name;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "parent_id", updatable = false, insertable = false, nullable=false)
@org.hibernate.annotations.IndexColumn(name = "parent_index")
List<Child> children = new ArrayList<Child>();
...
@Entity
public class Child {
@Id @GeneratedValue private Long id;
@Version private int version;
private String name;
@ManyToOne
@JoinColumn(name = "parent_id", updatable = false, insertable = false, nullable=false)
private Parent parent;
...
... dann Hibernate scheint viel optimierte SQL zu erzeugen:
Hibernate: insert into Parent (name, version, id) values (?, ?, ?)
Hibernate: insert into Child (name, price, version, parent_id, parent_index, id) values (?, ?, ?, ?, ?, ?)
Der Client-Code wie folgt aussieht:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Parent newParent = new Parent();
newParent.setName("Parent1");
Child newChild = new Child();
newChild.setName("Child1");
newParent.getChildren().add(newChild);
newChild.setParent(newParent);
em.persist(newParent);
em.flush();
tx.commit();
Ich benutze Hibernate-Entitymanager 3.4.0.GA.
Was fehlt mir? Ist der Hibernate Reference Guide nicht korrekt oder übersehe ich etwas?