Я не понимаю поведение Hibernate при сопоставлении двунаправленного списка. Операторы SQL, производимые Hibernate, кажутся мне не оптимальными. Может кто-нибудь просветить меня?Сопоставление двунаправленного списка с Hibernate
Сценарий следующий: У меня есть отношения один-ко-многим родитель-ребенок. Я сопоставляю это отношение с двунаправленным списком.
Согласно Hibernate Annotation Reference Guide (главе: двунаправленная связь с индексированными коллекциями) отображением должна выглядеть следующим образом:
@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;
...
Но в этом случае Hibernate производит три SQL заявления при сохраняющихся родителя с одним ребенком:
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=?
Третье утверждение представляется излишним, поскольку parent_id
и parent_index
, похоже, уже установлены во втором утверждении.
Когда я изменить отображение и повторить атрибуты «обновляемый = ЛОЖЬ, Вставные = ложь» к декларации @JoinColumn в Родитель, как это:
@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;
...
... потом Hibernate, кажется, производит гораздо более оптимизированный SQL:
Hibernate: insert into Parent (name, version, id) values (?, ?, ?)
Hibernate: insert into Child (name, price, version, parent_id, parent_index, id) values (?, ?, ?, ?, ?, ?)
клиентский код выглядит следующим образом:
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();
Я использую hibernate-entitymanager 3.4.0.GA.
Что мне не хватает? Не верное ли руководство по Hibernate, или я что-то не замечаю?