delete - JPA/Hibernate eliminar la entidad a veces no funciona
hibernate delete collection (3)
Tengo el siguiente código que generalmente funciona bien:
public void delete(T object)
{
EntityManager em = getPersistence().createEntityManager();
EntityTransaction et = em.getTransaction();
try
{
et.begin();
object = em.find(object.getClass(), object.getId());
em.remove(object);
em.flush();
et.commit();
}
catch(Exception e)
{
error("Unable to delete " + object.toString() + ": there are references to it.");
}
finally
{
if (et.isActive()) et.rollback();
em.close();
}
}
Para muchas de mis clases de entidades, esto solo funciona. Sin embargo, para dos de ellos no hace nada, no arroja ninguna excepción y no elimina el objeto. El registro de hibernación muestra que hibernate ejecuta una cantidad de consultas de selección, pero ni siquiera intenta ejecutar una eliminación.
Ya he intentado sugerencias encontradas en otras preguntas similares here y here , pero fue en vano (bueno, este último sugiere @Transactional
que no puedo usar, pero acabo de encerrar las declaraciones entre begin()
y commit()
lugar) .
No puedo encontrar lo que esas dos clases tienen más (o menos) que las otras. Usan @PrimaryKeyJoinColumn
al igual que casi todas las demás entidades que tengo, tienen @OneToMany
y @ManyToOne
al igual que ohters. Para ser honesto, tienen un campo @OneToOne(optional = false)
que hace referencia a otra clase y que otras entidades no tienen, pero yo no pasaría por la molestia de cambiar eso (y en consecuencia cambiar el esquema de la base de datos) a menos que dime que puede haber una razón para eso.
¿ @OneToOne
responsable @OneToOne
? ¿O está mi código de eliminación con errores?
¿Tiene asociaciones en este gráfico que en cascada persisten en la cosa que se borra? Si es así, la especificación JPA establece claramente que el proveedor debe cancelar la eliminación en dicho caso. Si este es el caso, Hibernate escribe una declaración de registro que dice "eliminación de entidad sin programación [...]". Puede ver eso al habilitar el registro de seguimiento en el registrador org.hibernate.event.internal.DefaultPersistEventListener
.
Si esta es la situación, deberá limpiar esas asociaciones según lo requerido por la especificación JPA.
Reemplazar la cascade = CascadeType.ALL
por orphanRemoval = true
en la asociación @OneToMany
da el resultado esperado: los registros secundarios se eliminan correctamente sin la necesidad de eliminar el registro principal.
Lástima que el error no se registre más claramente.
Tengo el mismo problema cuando sigo las cosas reunidas.
- Hibernate 3.6.10.Final
- Entidad matriz sin referencia al niño.
Alguna entidad Child con referencia al Padre. Es un código heredado.
class ChildEntity { @ManyToOne(cascade = CascadeType.ALL) private ParentEntity parent; }
La entidad secundaria se carga en el contexto de la sesión y luego se elimina de la tabla sin notificación JPA dentro de la transacción (procedimiento almacenado, sql nativo)
Entonces el padre no puede ser eliminado. Sin eliminación, sin excepción, solo mensaje de "eliminación de programación" en el registro TRACE.
Solución: eliminé el atributo de cascada. Fue un poco difícil para mí encontrar qué entidad Child bloquea la eliminación de los padres. Además, no entiendo por qué Child cascade afecta si elimino la entidad principal.