2012-06-28 7 views
4

J'ai eu un problème avec Hibernate 4 qui ne s'est pas produit dans Hibernate 3. Je suis en train de tester une classe dao de base qui a des méthodes génériques pour enregistrer, interroger, etc. . (ce n'est pas un devoir) J'utilise une connexion derby intégrée avec hibernate.hbm2ddl.auto = create-drop à des fins de test.Cascading save ne fonctionne pas avec Hibernate 4 et @OneToMany

EDIT: Correction de cascadeType. Toujours le même comportement. Même si j'ajoute tous les types de cascade disponibles de l'enum CascadeType, il échoue toujours, sauf si je mets CascadeType.ALL. Je ne sais pas ce que tout ce que vous ne pouvez pas énumérer spécifiquement.

Dans mes tests, je suivre des cours cartographiés:

@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; 
    } 
} 

Et puis j'essaie de sauver:

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(); 

Je reçois la trace suivante:

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) 
... 

J'ai remarqué le sql suivant en cours d'exécution:

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

Il semble qu'il essaie d'insérer dans la collection avant de mettre en cascade l'enregistrement de l'objet FooChild.

Si je change FooParent d'avoir ceci:

@OneToMany(cascade={CascadeType.ALL}) 

Le problème disparaît. Comme je l'ai dit, cela fonctionne avec hibernate 3, donc je ne sais pas pourquoi il se comporte différemment.

+0

'cascade = {CascadeType.MERGE, CascadeType.MERGE}': il n'y a pas de cascade pour SAVE_UPDATE ici. –

+0

désolé, j'ai essayé plusieurs choses, et j'ai une erreur dans ce que je suis revenu à. Il devrait lire CascadeType.PERSIST, CascadeType.MERGE – Matt

Répondre

1

save(), persist() et merge() sont trois opérations différentes. Si vous voulez en cascade l'opération save(), vous devez utiliser l'annotation Hibernate

@Cascade(CascadeType.SAVE_UPDATE) 

ou

cascade = CascadeType.ALL 

, qui comprennent également les opérations exclusives Hibernate.

+0

Merci. En général, j'essaie d'éviter les annotations spécifiques d'hibernation. Mon opinion générale est que la spécification de l'APP est plutôt incomplète. Sans oublier que l'API JPA est un peu plus difficile à utiliser que celle d'Hibernate. Surtout le CriteriaBuilder. – Matt

+0

Si vous voulez éviter les annotations spécifiques à Hibernate (que je peux comprendre), vous devriez également éviter les méthodes spécifiques à Hibernate telles que save(), saveOrUpdate() et update(). S'en tenir à 'persist()' et 'merge()', et vous n'aurez pas besoin d'annotations spécifiques à Hibernate. –

Questions connexes