Cómo solucionar el error "el objeto de Hibernate hace referencia a una instancia transitoria no guardada: guarde la instancia transitoria antes de vaciarla"

Resuelto Tushar Ahirrao asked hace 14 años • 35 respuestas

Recibo el siguiente error cuando guardo el objeto usando Hibernate

object references an unsaved transient instance - save the transient instance before flushing
Tushar Ahirrao avatar Feb 20 '10 23:02 Tushar Ahirrao
Aceptado

Debe incluir cascade="all"(si usa xml) o cascade=CascadeType.ALL(si usa anotaciones) en el mapeo de su colección.

Esto sucede porque tiene una colección en su entidad y esa colección tiene uno o más elementos que no están presentes en la base de datos. Al especificar las opciones anteriores, le indica a Hibernate que las guarde en la base de datos al guardar su padre.

Bozho avatar Feb 20 '2010 16:02 Bozho

Creo que esto podría ser solo una respuesta repetida, pero solo para aclarar, obtuve esto en un @OneToOnemapeo y en un archivo @OneToMany. En ambos casos, fue el hecho de que el Childobjeto que estaba agregando Parentaún no se había guardado en la base de datos. Entonces, cuando agregué el Childy Parentluego guardé el Parent, Hibernate arrojaría el "object references an unsaved transient instance - save the transient instance before flushing"mensaje al guardar el Padre.

Agregando la cascade = CascadeType.ALLreferencia Parent'sal Childproblema resuelto en ambos casos. Esto salvó el Childy el Parent.

Perdón por las respuestas repetidas, solo quería aclarar más a la gente.

@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "performancelog_id")
public PerformanceLog getPerformanceLog() {
    return performanceLog;
}
McDonald Noland avatar Jun 18 '2013 03:06 McDonald Noland

Introducción

Cuando se utiliza JPA e Hibernate, una entidad puede estar en uno de los siguientes 4 estados:

  • Nuevo : un objeto recién creado que nunca se ha asociado con una sesión de hibernación (también conocido como contexto de persistencia) y no está asignado a ninguna fila de la tabla de la base de datos se considera en estado nuevo o transitorio.

Para persistir necesitamos llamar explícitamente al persistmétodo o hacer uso del mecanismo de persistencia transitiva.

  • Persistente : una entidad persistente se ha asociado con una fila de la tabla de la base de datos y está siendo administrada por el contexto de persistencia actualmente en ejecución.

Cualquier cambio realizado en dicha entidad será detectado y propagado a la base de datos (durante el tiempo de vaciado de la sesión).

  • Separado : una vez que se cierra el contexto de persistencia que se está ejecutando actualmente, todas las entidades administradas anteriormente se desconectan. Ya no se realizará un seguimiento de los cambios sucesivos y no se realizará ninguna sincronización automática de la base de datos.

  • Eliminado : aunque JPA exige que solo se permita eliminar entidades administradas, Hibernate también puede eliminar entidades separadas (pero solo mediante una removellamada a un método).

Transiciones de estado de entidad

Para mover una entidad de un estado a otro, puede utilizar los métodos persisto .removemerge

Estados de la entidad JPA

Solucionando el problema

El problema que estás describiendo en tu pregunta:

object references an unsaved transient instance - save the transient instance before flushing

se produce al asociar una entidad en el estado New a una entidad que está en el estado Managed .

Esto puede suceder cuando asocia una entidad secundaria a una colección de uno a muchos en la entidad principal y la colección no realiza cascadelas transiciones de estado de la entidad.

Por lo tanto, puede solucionar este problema agregando cascada a la asociación de entidad que desencadenó este error, de la siguiente manera:

La @OneToOneAsociación

@OneToOne(
    mappedBy = "post",
    orphanRemoval = true,
    cascade = CascadeType.ALL)
private PostDetails details;

Observe el CascadeType.ALLvalor que agregamos para el cascadeatributo.

La @OneToManyAsociación

@OneToMany(
    mappedBy = "post", 
    orphanRemoval = true,
    cascade = CascadeType.ALL)
private List<Comment> comments = new ArrayList<>();

Nuevamente, CascadeType.ALLes adecuado para las @OneToManyasociaciones bidireccionales.

Ahora, para que la cascada funcione correctamente de forma bidireccional, también debe asegurarse de que las asociaciones principal e secundaria estén sincronizadas.

La @ManyToManyAsociación

@ManyToMany(
    mappedBy = "authors",
    cascade = {
        CascadeType.PERSIST, 
        CascadeType.MERGE
    }
)
private List<Book> books = new ArrayList<>();

En una @ManyToManyasociación, no puede usar CascadeType.ALLo, orphanRemovalya que esto propagará la transición del estado de eliminación de la entidad de una entidad principal a otra entidad principal.

Por lo tanto, para @ManyToManylas asociaciones, normalmente las operaciones CascadeType.PERSISTu se ponen en cascada CascadeType.MERGE. Alternativamente, puede expandirlo a DETACHo REFRESH.

Vlad Mihalcea avatar Dec 29 '2019 20:12 Vlad Mihalcea