Tengo problemas con la configuración de JPA/Hibernate (3.5.3), donde tengo una entidad, una clase "Cuenta", que tiene una lista de entidades secundarias, instancias de "Contacto" . Estoy tratando de poder agregar/eliminar instancias de contacto en una lista <Contacto> propiedad de la cuenta.Infracciones de restricción de activación de Hibernate usando orphanRemoval
Agregando una nueva instancia en el conjunto y llamando a saveOrUpdate (cuenta) persiste todo encantador. Si luego selecciono eliminar el contacto de la lista y llamo de nuevo a saveOrUpdate, el SQL Hibernate parece producir el ajuste de la columna account_id a null, lo que infringe una restricción de la base de datos.
¿Qué estoy haciendo mal?
El código siguiente es claramente un resumen simplificado, pero creo que cubre el problema ya que estoy viendo los mismos resultados en código diferente, que realmente es así de simple.
SQL:
CREATE TABLE account (INT account_id);
CREATE TABLE contact (INT contact_id, INT account_id REFERENCES account (account_id));
Java:
@Entity
class Account {
@Id
@Column
public Long id;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "account_id")
public List<Contact> contacts;
}
@Entity
class Contact {
@Id
@Column
public Long id;
@ManyToOne(optional = false)
@JoinColumn(name = "account_id", nullable = false)
public Account account;
}
Account account = new Account();
Contact contact = new Contact();
account.contacts.add(contact);
saveOrUpdate(account);
// some time later, like another servlet request....
account.contacts.remove(contact);
saveOrUpdate(account);
Resultado:
UPDATE contact SET account_id = null WHERE contact_id = ?
Edición # 1:
Puede ser que esto es en realidad un error http://opensource.atlassian.com/projects/hibernate/browse/HHH-5091
Edición # 2:
tengo una solución que parece funcionar, pero implica el uso de la API de Hibernate
class Account {
@SuppressWarnings("deprecation")
@OneToMany(cascade = CascadeType.ALL, mappedBy = "account")
@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
@JoinColumn(name = "account_id", nullable = false)
private Set<Contact> contacts = new HashSet<Contact>();
}
class Contact {
@ManyToOne(optional = false)
@JoinColumn(name = "account_id", nullable = false)
private Account account;
}
Desde Hibernate CascadeType.DELETE_ORPHAN está en desuso, estoy teniendo a Supongamos que ha sido reemplazado por la versión JPA2, pero la implementación le falta algo.
Creo que lo que hizo funcionar la cosa, es la opción nullable = false en @JoinColumn y opcional = falso en @ManyToOne, no la cascada de hibernación personalizada. – Thierry
Incluso cuando agregué las marcas con opción de nulos y opcionales, aún falló, pero esta vez cuando se dio cuenta de que había creado un escenario donde violaba una restricción anotada, en lugar de una SQL. Parece que todavía hay algunos problemas con 3.5.3 y JPA2, ya que no puedo hacer que @ElementCollection actúe bien. – ptomli
establezca CascadeType, ya que ALL realizará todas las opertaciones sin tener que ser explícito como DELETE_ORPHAN –