update one many annotation all hibernate one-to-many cascade hibernate-annotations

annotation - Hibernate: OneToMany salva a los niños en cascada



one to many jpa (4)

En la clase Padre hay una lista de listas. Cuando se guarde el padre, los hijos que se han agregado o cambiado se guardarán / actualizarán por hibernación.

He encontrado muchas explicaciones sobre esto, sin embargo, simplemente no consigo que funcione.

Parent.class try A

@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.class try 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;

los hijos se agregan a un nuevo padre. Luego ambos son salvados por

sessionFactory.getCurrentSession().saveOrUpdate(parent);

Sin embargo, al lavar, me sale el siguiente error:

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)

¿Alguien ve mi error?

¡¡Muchas gracias!!


Necesitaba una manera de insertar una entidad con una nueva entidad unida (hijos) juntas. Una forma de hacerlo es separar las acciones (por ejemplo, para guardar primero la entidad unida y luego para guardar la entidad principal). Sin embargo, Hibernate admite la inserción de una nueva entidad con una nueva entidad unida. Vea un ejemplo de cómo: Cómo insertar niños OneToMany por cascada


Prueba esto:

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

Uso

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

Nota: No olvide configurar el objeto primario en el objeto secundario o obtendrá TABLE_CHILD.PARENT_ID null / empty


Supongo que si responde a la pregunta del primer comentario, llegaremos a esta situación:

  • tienes un padre ya persistido
  • tienes nuevos objetos secundarios, que aún no se han persistido
  • agregas los hijos al padre y haces saveOrUpdate

En ese caso, hibernar solo conecta en cascada el guardado o la actualización a los hijos, pero no se pueden guardar ni actualizar porque aún no han sido persistentes. Y ahora Hibernate dice simplemente "No puedo actualizar una entidad no persistente"

En una frase: Hibernate solo conecta en cascada lo que se emite a la cascada. En este caso, emite un "SAVE_UPDATE" , que se coloca en cascada y luego a los hijos. Supongo que esperabas que Hibernate fuera inteligente y cambiara para persistir por los niños aquí. Pero no es así como funciona Hibernate aquí, también me encontré con situaciones similares antes. Un poco confuso, pero si alguna vez entendiste cómo funciona la cascada, verás tales situaciones.


Tu prueba de Parent.class A parece ya correcta. Pero para conectar en cascada al hijo mientras se guarda el padre, debe poner la cascada en el lado del propietario (en uno a muchos, es la entidad la que tiene la clave externa).

Prueba esto

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

y en tu hijo.clase

@Entity public class Child { @ManyToOne @Cascade(value={org.hibernate.annotations.CascadeType.ALL}) @JoinColumn(name="PARENT_ID") protected Parent parent; }