Hibernate: OneToMany sauver des enfants en cascade

dans la classe Parent il y a une liste. Lorsque le parent est sauvé, les enfants qui ont été ajoutés ou modifiés sont sauvés / mis à jour par hibernation.

j'ai trouvé beaucoup d'explications sur ce point, cependant, je n'arrive pas à le faire fonctionner.

Parent.classe essayez Un

@Entity
public class Parent {
// id and other attributes
@OneToMany(mappedBy = "parent")
@org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.ALL)
protected List<child> children;
Parent.classe essayez de B

@Entity
public class Parent {
// id and other attributes
  @OneToMany(mappedBy = "parent", cascade = { javax.persistence.CascadeType.ALL },
 orphanRemoval = true)
 @org.hibernate.annotations.Cascade({ 
 org.hibernate.annotations.CascadeType.PERSIST,
 org.hibernate.annotations.CascadeType.MERGE,
 org.hibernate.annotations.CascadeType.REFRESH,
 org.hibernate.annotations.CascadeType.SAVE_UPDATE,
 org.hibernate.annotations.CascadeType.REPLICATE,
 org.hibernate.annotations.CascadeType.LOCK,
 org.hibernate.annotations.CascadeType.DETACH })
protected List<child> children;

les enfants sont ajoutés à un nouveau parent. Ensuite les deux sont sauvés par

sessionFactory.getCurrentSession().saveOrUpdate(parent);

en tirant la chasse d'eau, cependant, j'obtiens ce qui suit erreur:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: de.pockettaxi.backend.model.ride.RideSingle
at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:243)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:456)
at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:265)
at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:275)
at org.hibernate.type.TypeHelper.findDirty(TypeHelper.java:295)
at org.hibernate.persister.entity.AbstractEntityPersister.findDirty(AbstractEntityPersister.java:3378)
at org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck(DefaultFlushEntityEventListener.java:520)
at org.hibernate.event.def.DefaultFlushEntityEventListener.isUpdateNecessary(DefaultFlushEntityEventListener.java:230)
at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:154)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)

Est-ce que quelqu'un voit mon erreur?

Merci beaucoup!!

18
demandé sur Steve Eastwood 2012-03-11 01:48:46

4 réponses

je suppose que si vous répondez à la question à partir de la première observation, nous viendrons à cette situation:

  • vous avez déjà persisté parent
  • vous avez de nouveaux objets d'enfant, qui n'ont pas encore persisté
  • vous ajoutez les enfants au parent et faites saveOrUpdate

dans ce cas, hibernate envoie simplement la sauvegarde ou la mise à jour en cascade aux enfants, mais ils ne peuvent pas être sauvegardés ou mis à jour car ils n'ont pas encore été persistants. Et maintenant hiberné dit simplement "Je ne peux pas mettre à jour une entité non persistante"

en une phrase: L'hibernation n'entraîne qu'une cascade de ce qui est délivré à cascade. Dans ce cas, vous délivrer un "SAVE_UPDATE", qui se répercute ensuite sur les enfants. Je suppose que vous vous attendiez à ce que Hibernate soit intelligent et change pour persister pour les enfants ici. Mais ce N'est pas ainsi que L'hibernation fonctionne ici, je suis tombé sur des situations similaires avant, aussi. Un peu confus, mais si vous avez une fois obtenu comment cascade fonctionne, vous verrez situation.

14
répondu Markus 2012-03-11 08:52:04

Votre Parent.la classe A semble déjà correcte. Mais pour cascader l'enfant tout en sauvant le parent, vous devez mettre la cascade du côté du propriétaire (dans one-to-many, c'est l'entité qui ont la clé étrangère).

Essayez ceci

@Entity
public class Parent {
    @OneToMany(mappedBy = "parent")
    protected List<Child> children;
}

et à votre Enfant.classe

@Entity
public class Child {
    @ManyToOne
    @Cascade(value={org.hibernate.annotations.CascadeType.ALL})
    @JoinColumn(name="PARENT_ID")
    protected Parent parent;
}
10
répondu Joshua H 2015-11-26 09:08:46

j'avais besoin d'un moyen pour insérer une entité avec une nouvelle entité jointe (enfants) ensemble. Une façon de le faire est de séparer les actions (par exemple, pour enregistrer le rejoint entité d'abord, puis d'enregistrer la principale entité). Cependant, Hibernate soutient l'insertion d'une nouvelle entité avec une nouvelle entité jointe. Voir un exemple: Comment insérer des enfants OneToMany par cascade

5
répondu Ilanh 2012-08-05 07:09:02

essaye ceci:

@Entity
@Table(name = "TABLE_PARENT")
public class Parent{
    @OneToMany(mappedBy="parent", cascade=CascadeType.PERSIST)
    private List<Child> children;
}

@Entity
@Table(name = "TABLE_CHILD")
public class Child{
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="PARENT_ID")
    private Parent parent;
}

Utilisation

public void save(){
  Parent parent = new Parent();
  List<Child> children = new ArrayList<>();
  Child child = new Child();
  child.setParent(parent);
  children.add(child);
  parent.setChildren(children);

  parentRepository.save(parent);
}

Remarque: n'oubliez pas de configurer le parent sur l'objet child ou vous obtiendrez TABLE_CHILD.PARENT_ID null / empty

3
répondu Arif Nazar Purwandaru 2017-07-28 01:59:19