Error de Hibernación: org.hibernate.NonUniqueObjectException: un objeto diferente con el mismo valor de identificador ya estaba asociado con la sesión

Tengo dos objetos de usuario y mientras trato de guardar el objeto usando

session.save(userObj); 

Estoy teniendo el siguiente error:

 Caused by: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.pojo.rtrequests.User#com.pojo.rtrequests.User@d079b40b] 

Estoy creando la sesión usando

 BaseHibernateDAO dao = new BaseHibernateDAO(); rtsession = dao.getSession(userData.getRegion(), BaseHibernateDAO.RTREQUESTS_DATABASE_NAME); rttrans = rtsession.beginTransaction(); rttrans.begin(); rtsession.save(userObj1); rtsession.save(userObj2); rtsession.flush(); rttrans.commit(); rtsession.close(); // in finally block 

También intenté hacer la session.clear() antes de guardar, todavía no tuve suerte.

Esto es para el primero que recibo el objeto de sesión cuando llega una solicitud del usuario, entonces entiendo por qué está diciendo que el objeto está presente en la sesión.

¿Alguna sugerencia?

He tenido este error muchas veces y puede ser bastante difícil de localizar …

Básicamente, lo que hibernate está diciendo es que tienes dos objetos que tienen el mismo identificador (misma clave principal) pero no son el mismo objeto.

Sugeriría que desgloses tu código, es decir, comente los bits hasta que desaparezca el error y luego devuelve el código hasta que vuelva y deberías encontrar el error.

A menudo sucede a través de salvaciones en cascada donde hay una cascada de salvar entre el objeto A y B, pero el objeto B ya se ha asociado con la sesión, pero no en la misma instancia de B.

¿Qué generador de llave primaria estás usando?

La razón por la que pregunto es que este error está relacionado con la forma en que está diciendo hibernate para determinar el estado persistente de un objeto (es decir, si un objeto es persistente o no). El error podría estar sucediendo porque hibernate está tratando de persistir y el objeto que ya es persistente. De hecho, si usa guardar, hibernate intentará y persistirá ese objeto, y tal vez ya exista un objeto con la misma clave principal asociada a la sesión.

Ejemplo

Suponiendo que tiene un objeto de clase Hibernate para una tabla con 10 filas basadas en una combinación de teclas principal (columna 1 y columna 2). Ahora, ha eliminado 5 filas de la tabla en algún punto del tiempo. Ahora, si intenta agregar las mismas 10 filas nuevamente, mientras hibernate intenta persistir en los objetos en la base de datos, se agregarán 5 filas que ya fueron eliminadas sin errores. Ahora las 5 filas restantes que ya existen, arrojarán esta excepción.

Entonces, el enfoque fácil sería verificar si ha actualizado / eliminado cualquier valor en una tabla que es parte de algo y luego está tratando de insertar los mismos objetos nuevamente

Este es solo un punto donde Hibernate genera más problemas de los que resuelve. En mi caso, hay muchos objetos con el mismo identificador 0, porque son nuevos y no tienen uno. El db los genera. En algún lugar he leído que 0 señales no se han configurado. La forma intuitiva de persistir es iterar sobre ellos y decir hibernación para guardar los objetos. Pero no puedes hacer eso – “Por supuesto, debes saber que hibernate funciona de esta manera, por lo tanto, tienes que …” Así que ahora puedo intentar cambiar Ids a Long en lugar de long y ver si funciona. Al final, es más fácil hacerlo con un mapeador simple por su cuenta, ya que hibernate es solo una carga adicional no transparente. Otro ejemplo: intentar leer los parámetros de una base de datos y conservarlos en otra fuerza obliga a hacer casi todo el trabajo manualmente. Pero si tiene que hacerlo de todos modos, usar hibernate es solo trabajo adicional.

USe session.evict(object); La función del método evict() se utiliza para eliminar la instancia de la memoria caché de la sesión. Por lo tanto, por primera vez, guarde el objeto, guarde el objeto llamando al método session.save(object) antes de expulsar el objeto del caché. Del mismo modo, actualice el objeto llamando a session.saveOrUpdate(object) o session.update(object) antes de llamar a evict ().

Como alguien ya señaló anteriormente, me encontré con este problema cuando tuve cascade=all en ambos extremos de una relación de one-to-many , así que supongamos que A -> B (uno a muchos de A y muchos a uno desde B) y estaba actualizando la instancia de B en A y luego llamando a saveOrUpdate (A), estaba resultando en una solicitud de guardado circular, es decir, el guardado de A dispara el salvador de B que activa el salvado de A … y en el tercer caso como el se intentó agregar entidad (de A) a sessionPersistenceContext se lanzó la excepción duplicateObject.
Podría resolverlo eliminando la cascada de un extremo.

Esto puede suceder cuando ha utilizado el mismo objeto de sesión para leer y escribir. ¿Cómo? Digamos que ha creado una sesión. Leíste un registro de la tabla de empleados con la clave primaria Emp_id = 101 Ahora has modificado el registro en Java. Y va a guardar el registro de Empleado en la base de datos. no hemos cerrado la sesión en ningún lado aquí. Como el objeto que se leyó también persiste en la sesión. Entra en conflicto con el objeto que deseamos escribir. De ahí viene este error.

Obtenga el objeto dentro de la sesión, aquí un ejemplo:

 MyObject ob = null; ob = (MyObject) session.get(MyObject.class, id); 

Me encontré con este problema por:

  1. Eliminar un objeto (usando HQL)
  2. Almacenamiento inmediato de un nuevo objeto con la misma identificación

Lo resolví vaciando los resultados después de la eliminación y borrando el caché antes de guardar el nuevo objeto

 String delQuery = "DELETE FROM OasisNode"; session.createQuery( delQuery ).executeUpdate(); session.flush(); session.clear(); 

También encontré este problema y tuve un momento difícil para encontrar el error.

El problema que tuve fue el siguiente:

El objeto ha sido leído por un Dao con una sesión de hibernación diferente.

Para evitar esta excepción, simplemente vuelva a leer el objeto con el dao que va a guardar / actualizar este objeto más adelante.

asi que:

 class A{ readFoo(){ someDaoA.read(myBadAssObject); //Different Session than in class B } } class B{ saveFoo(){ someDaoB.read(myBadAssObjectAgain); //Different Session than in class A [...] myBadAssObjectAgain.fooValue = 'bar'; persist(); } } 

¡Espero que a algunas personas les ahorre mucho tiempo!

¿Son correctas sus asignaciones de Id? Si la base de datos es responsable de crear el identificador a través de un identificador, debe asignar su userobject a ese …

Compruebe si olvidó poner @GenerateValue para la columna @Id. Tuve el mismo problema con muchas a muchas relaciones entre Película y Género. El progtwig arrojó Hibernate Error: org.hibernate.NonUniqueObjectException: un objeto diferente con el mismo valor de identificador ya estaba asociado con el error de sesión. Descubrí más tarde que solo tenía que asegurarme de tener @GenerateValue en el método de obtención de GenreId.

solo revisa la identificación si toma nulo o 0 me gusta

 if(offersubformtwo.getId()!=null && offersubformtwo.getId()!=0) 

en agregar o actualizar donde el contenido se establece de forma a Pojo

Encontré este problema al eliminar un objeto, ni desalojar ni borrar me ayudó.

 /** * Deletes the given entity, even if hibernate has an old reference to it. * If the entity has already disappeared due to a db cascade then noop. */ public void delete(final Object entity) { Object merged = null; try { merged = getSession().merge(entity); } catch (ObjectNotFoundException e) { // disappeared already due to cascade return; } getSession().delete(merged); } 

Tuve un problema similar. En mi caso, había olvidado establecer el valor de increment_by en la base de datos para que sea el mismo que el usado por el cache_size y el cache_size allocationSize . (Las flechas apuntan a los atributos mencionados)

SQL:

 CREATED 26.07.16 LAST_DDL_TIME 26.07.16 SEQUENCE_OWNER MY SEQUENCE_NAME MY_ID_SEQ MIN_VALUE 1 MAX_VALUE 9999999999999999999999999999 INCREMENT_BY 20 <- CYCLE_FLAG N ORDER_FLAG N CACHE_SIZE 20 <- LAST_NUMBER 180 

Java:

 @SequenceGenerator(name = "mySG", schema = "my", sequenceName = "my_id_seq", allocationSize = 20 <-) 

De lo contrario, de lo que dijo wbdarby , incluso puede suceder cuando se busca un objeto dando el identificador del objeto a un HQL. En el caso de intentar modificar los campos del objeto y guardarlo de nuevo en DB (la modificación podría ser insertar, eliminar o actualizar) en la misma sesión , aparecerá este error. Intente borrar la sesión de hibernación antes de guardar su objeto modificado o crear una nueva sesión.

Espero haber ayudado 😉

Tengo el mismo error al reemplazar mi Set con uno nuevo de Jackson.

Para resolver esto guardo el conjunto existente, retainAll conjunto anterior el elemento desconocido en la nueva lista con retainAll . Luego agrego los nuevos con addAll .

  this.oldSet.retainAll(newSet); this.oldSet.addAll(newSet); 

No es necesario tener la sesión y manipularla.

Prueba esto. ¡Lo de abajo funcionó para mí!

En el archivo hbm.xml

  1. Necesitamos establecer el atributo de dynamic-update de la etiqueta de clase en true :

      
  2. Establezca el atributo de clase de la etiqueta del generador debajo de la columna única de identity :

      

Nota: Establezca la columna única en identity lugar de assigned .

Otra cosa que funcionó para mí fue hacer que la instancia sea una variable larga en lugar de larga

Tenía mi variable de clave principal ID larga; cambiándolo a Identificación larga; trabajó

Todo lo mejor

Siempre puedes hacer un lavado de sesión. Flush sincronizará el estado de todos tus objetos en la sesión (por favor, alguien me corrige si estoy equivocado), y tal vez eso resolvería tu problema en algunos casos.

Implementar tus propios iguales y hashcode también puede ayudarte.

Puede verificar su configuración de Cascade. La configuración de Cascade en sus modelos podría estar causando esto. Eliminé la configuración de Cascade (Esencialmente no permitía insertar / actualizar Cascade) y esto resolvió mi problema

Encontré este error también. Lo que funcionó para mí es asegurarme de que la clave primaria (que se autogenera) no es una PDT (es decir, long, int, ect), sino un objeto (es decir, Long, Integer, etc.)

Cuando crea su objeto para guardarlo, asegúrese de pasar nulo y no 0.

Soy nuevo en NHibernate, y mi problema fue que utilicé una sesión diferente para consultar mi objeto que para guardarlo. Entonces la sesión de ahorro no sabía sobre el objeto.

Parece obvio, pero al leer las respuestas anteriores buscaba en todas partes 2 objetos, no 2 sesiones.

¿Esto ayuda?

 User userObj1 = new User(); User userObj2 = userObj1; . . . rtsession.save(userObj1); rtsession.save(userObj2); 

@GeneratedValue (estrategia = GenerationType.IDENTITY), la adición de esta anotación a la propiedad de la clave primaria en su bean de entidad debería resolver este problema.

Resolví este problema.
En realidad, esto está sucediendo porque olvidamos la implementación del tipo de generador de PK en la clase de bean. Entonces hazlo de cualquier tipo como

 @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; 

cuando persistimos en los objetos de Bean, cada objeto adquiere la misma ID, por lo que se guarda el primer objeto, cuando persiste otro objeto HIB FW a través de este tipo de Exception: org.hibernate.NonUniqueObjectException: un objeto diferente con el mismo valor de identificador ya asociado con la sesión.

He resuelto un problema similar como ese:

 plan = (FcsRequestPlan) session.load(plan.getClass(), plan.getUUID()); while (plan instanceof HibernateProxy) plan = (FcsRequestPlan) ((HibernateProxy) plan).getHibernateLazyInitializer().getImplementation(); 

antes de la posición donde comienzan los objetos repetitivos, debe cerrar la sesión y luego debe comenzar una nueva sesión

 session.close(); session = HibernateUtil.getSessionFactory().openSession(); 

así que de esta manera en una sesión no hay más de una entidad que tenga el mismo identificador.

El problema ocurre porque en la misma sesión de hibernación intentas guardar dos objetos con el mismo identificador. Existen dos soluciones:

  1. Esto sucede porque no ha configurado correctamente su archivo mapping.xml para los campos de id como a continuación:

         
  2. Sobrecargue el método getession para aceptar un parámetro como isSessionClear, y borre la sesión antes de devolver la sesión actual como se muestra a continuación

     public static Session getSession(boolean isSessionClear) { if (session.isOpen() && isSessionClear) { session.clear(); return session; } else if (session.isOpen()) { return session; } else { return sessionFactory.openSession(); } } 

Esto hará que los objetos de sesión existentes se borren e incluso si la hibernación no genera un identificador único, suponiendo que haya configurado su base de datos correctamente para una clave principal usando algo como Auto_Increment, debería funcionar para usted.

Una solución para resolver este problema es tratar de leer el objeto de hibernación caché / db antes de realizar cualquier actualización y luego persistir.

Ejemplo:

  OrderHeader oh = orderHeaderDAO.get(orderHeaderId); oh.setShipFrom(facilityForOrder); orderHeaderDAO.persist(oh); 

Nota: tenga en cuenta que esto no soluciona la causa raíz, pero resuelve el problema.

Tarde a la fiesta, pero puede ayudar a los futuros usuarios:

getsession() este problema cuando selecciono un registro usando getsession() y de nuevo actualizo otro registro con el mismo identificador usando la misma sesión que causa el problema. Código agregado a continuación.

 Customer existingCustomer=getSession().get(Customer.class,1); Customer customerFromUi;// This customer details comiong from UI with identifer 1 getSession().update(customerFromUi);// Here the issue comes 

Esto nunca debería hacerse. La solución es desalojar la sesión antes de la actualización o cambiar la lógica comercial.

Puede usar session.merge(obj) , si está haciendo guardar con diferentes sesiones con el mismo objeto persistente de identificador.
Funcionó, tuve el mismo problema antes.