2010-08-22 20 views
5

tengo una entidad que contiene otras dos entidades con relación @ManyToOne.Hibernate y NonUniqueObjectException

@Entity 
public class A extends Serializable{ 

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

    @ManyToOne 
    @Cascade(CascadeType.SAVE_UPDATE) 
    private B b; 

    @ManyToOne 
    @Cascade(CascadeType.SAVE_UPDATE) 
    private C c; 

} 

si trato de guardar un Un ejemplo que tienen "B_ID" y "C_ID" de otro Un registro me da la excepción:

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

Por ejemplo:

A table 
| ID | B_ID | C_ID | 
| 1 |  1 | null | // this works 
| 2 | null |  1 | // this works 
| 3 |  1 |  x | // this throws the exception 
| 4 |  x |  1 | // this throws the exception 

x=any value of existent B/C_ID 

B_ID y C_ID no son únicos en mi modelo y (B_ID + C_ID) no es una restricción única.

¿Qué puedo hacer?

Gracias de antemano.

Respuesta

15

Hibernate no se queja de la unicidad de la base de datos aquí, se queja de que la actual Session ya contiene un objeto con la misma ID que un objeto nuevo que está intentando guardar. No lo permitirá: Hibernate tiene un requisito estricto de que un ID determinado no puede ser representado por dos objetos diferentes en el ámbito de una sola sesión.

En algún momento, su aplicación ha guardado una entidad con ese mismo ID, y ese objeto ya está "registrado" en la sesión. Es difícil decir en este caso específico de qué ID se está quejando, ya que el texto de la excepción no está claro. Intente eliminar temporalmente las directivas en cascada y vea si continúan, intente reducirlas.

Si es necesario, puede forzar la sesión para "olvidar" cualquier objeto existente para una ID determinada (usando Session.evict() en la API de Hibernate, o EntityManager.detach() en la API de JPA 2.0), pero esa no es una solución muy elegante.

Para reiterar: esta excepción no tiene nada que ver con las restricciones de la base de datos, se trata de que Hibernate proteja la consistencia de su estado interno en memoria.

+0

Gracias, las únicas cosas que cargo de db son B y C, y las uso en el objeto A. Pero B y C tienen CascadeType.SAVE_UPDATE, por lo que no se guardan de nuevo, sino que solo se actualizan ... espero ... – blow

+0

Los problemas también aparecen al inicio, cuando la sesión es nueva. – blow

+0

eliminar las directivas en cascada funciona bien, pero ... ¿POR QUÉ? Sin "Cascade.SAVE_UPDATE" hibernate debería intentar volver a GUARDAR "A" y "B" que ya están presentes en db y así lanzar una excepción, pero funciona en su lugar ... ¿por qué? – blow