2009-02-02 9 views
7

Я не понимаю поведение 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, или я что-то не замечаю?

ответ

6

Хорошо, я недостаточно читал Руководство по аннотациям.

В главе 2.2.5.3.1.1. Bidirectional говорится ясно:

Для отображения двунаправленного один ко многим, со стороной один-ко-многим, как со стороны имущего, вы должны удалить элемент mappedBy и установить многие к одному @JoinColumn как вставляемое и обновляемое значение false. Это решение, очевидно, не оптимизировано и будет содержать некоторые дополнительные инструкции UPDATE.

Возможно, это не помешает повторить эту информацию в Chapter 2.4.6.2.1. Bidirectional association with indexed collections.

Теперь остается вопрос: если я повторяю атрибуты @JoinColumn «updatable = false» и «insertable = false» на родительском (см. Код в первом сообщении), дополнительные инструкции по обновлению, похоже, не получаются ... это законное обходное решение? Или это приводит к другой проблеме?

 Смежные вопросы

  • Нет связанных вопросов^_^