2012-06-28 1 views
4

У меня возникла проблема с Hibernate 4, которая не произошла в Hibernate 3. Я тестирую базовый класс dao, который имеет общие методы для сохранения, запросов и т. Д. . (не это не домашнее задание). Я использую встроенное дерби соединение с hibernate.hbm2ddl.auto = create-drop для целей тестирования.Каскадное сохранение не работает с Hibernate 4 и @OneToMany

EDIT: Фиксация каскадаТип. Все-таки такое же поведение. Даже если я добавлю все доступные типы каскадов из перечисления CascadeType, он все равно терпит неудачу, если я не поставлю CascadeType.ALL. Не уверен, что ВСЕ есть, что вы не можете специально перечислить.

В моих тестах я следующие отображенные классы:

@Entity 
@Table(name="FOO_CHILD") 
public class FooChild { 
    @Id 
    @Column(name="FOO_ID") 
    private Long id; 

    @Column(name="NAME") 
    private String name; 

    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

@Entity 
@Table(name="FOO_PARENT") 
public class FooParent { 
    @Id 
    @Column(name="FOO_PARENT_ID") 
    private Long id; 

    @Column(name="NAME") 
    private String name; 

    @Fetch(FetchMode.SELECT) 
    @Type(type="long") 
    @OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE}) 
    @JoinTable(name="FOO_PARENT_FOO", 
      joinColumns={@JoinColumn(referencedColumnName="FOO_PARENT_ID")}, 
      inverseJoinColumns={@JoinColumn(referencedColumnName="FOO_ID")}) 
    private List<Foo> fooChild; 

    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public List<Foo> getFooChild() { 
     return fooChild; 
    } 

    public void setFooChild(List<Foo> fooChild) { 
     this.fooChild = fooChild; 
    } 
} 

И тогда я пытаюсь сохранить:

FooChild fooChild = new FooChild(); 
fooChild.setId(1L); 
fooChild.setName("fooChild"); 

FooParent fooParent = new FooParent(); 
fooParent.setId(1L); 
fooParent.setName("fooParent"); 
fooParent.setFooChild(new ArrayList<FooChild>(Arrays.asList(fooChild))); 

session.save(fooParent); 
session.flush(); 
session.clear(); 

я получаю следующий след:

org.hibernate.exception.ConstraintViolationException: INSERT on table 'FOO_PARENT_FOO' caused a violation of foreign key constraint 'FKF18290CAECA19CB8' for key (1). The statement has been rolled back. 
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:74) 
... 

Я заметил выполняется следующее sql:

Hibernate: 
    insert 
    into 
     foo_parent 
     (name, foo_parent_id) 
    values 
     (?, ?, ?, ?) 
Hibernate: 
    insert 
    into 
     foo_parent_foo 
     (foo_parent, foo_child) 
    values 
     (?, ?) 

Кажется, он пытается вставить в коллекцию до каскадирования сохранения до объекта FooChild.

Если я изменить FooParent, чтобы это:

@OneToMany(cascade={CascadeType.ALL}) 

Проблема уходит.

Как я уже сказал, это работает с hibernate 3, поэтому я не уверен, почему он ведет себя по-другому.

+0

'cascade = {CascadeType.MERGE, CascadeType.MERGE}': здесь нет каскада для SAVE_UPDATE. –

+0

Извините, я попробовал несколько вещей и имею ошибку в том, к чему я вернулся. Он должен читать CascadeType.PERSIST, CascadeType.MERGE – Matt

ответ

1

save(), persist() и merge() - это три различных операции. Если вы хотите каскадные save() операцию, вам нужно использовать гибернации аннотации

@Cascade(CascadeType.SAVE_UPDATE) 

или

cascade = CascadeType.ALL 

, которые также включают в себя собственные операции Hibernate.

+0

Спасибо. В общем, я стараюсь избегать аннотаций спящего режима. Это мое общее мнение, хотя спецификация JPA довольно неполна. Не говоря уже о JPA API довольно сложнее в использовании, чем в спящем режиме. Особенно CriteriaBuilder. – Matt

+0

Если вы хотите избежать аннотаций, специфичных для Hibernate (которые я могу понять), вы также можете избежать специальных методов, связанных с Hibernate, таких как save(), saveOrUpdate() и update(). Придерживайтесь 'persist()' и 'merge()', и вам не понадобятся аннотации для Hibernate. –