Esta es el arreglo más acertada que encomtrarás aportar, sin embargo obsérvala pausadamente y analiza si se adapta a tu proyecto.
Solución:
Las opciones son:
- use la configuración cascade.Remove en el mapeo, cargando entidades y llamando a em.remove en cada
- Use la eliminación masiva en la entidad principal y tenga configurada la opción de base de datos “ON DELETE CASCADE” para que la base de datos realice la eliminación en cascada por usted. EclipseLink tiene una anotación @CascadeOnDelete que le permite saber que “ON DELETE CASCADE” está configurado en una relación, o para crearlo si usa JPA para la generación de DDL: http://eclipse.org/eclipselink/documentation/2.5/jpa/extensions /a_cascadeondelete.htm
- Utilice varias eliminaciones masivas para eliminar elementos secundarios a los que se pueda hacer referencia antes de eliminar la entidad principal. Por ejemplo: “Eliminar DE Hijo c donde c.padre = (seleccione p de Padre P donde [delete-conditions])” y “Eliminar DE padre p donde [delete-conditions]” Consulte la sección 10.2.4 de http://docs.oracle.com/middleware/1212/toplink/OTLCG/queries.htm#OTLCG94370 para obtener detalles.
¿Cómo funciona JPA CriteriaDelete?
Un JPA CriteriaDelete
genera una declaración de eliminación masiva de JPQL, que se analiza en una declaración de eliminación masiva de SQL.
Entonces, el siguiente JPA CriteriaDelete
declaración:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaDelete delete = builder.createCriteriaDelete(PostComment.class);
Root root = delete.from(PostComment.class);
int daysValidityThreshold = 3;
delete.where(
builder.and(
builder.equal(
root.get("status"),
PostStatus.SPAM
),
builder.lessThanOrEqualTo(
root.get("updatedOn"),
Timestamp.valueOf(
LocalDateTime
.now()
.minusDays(daysValidityThreshold)
)
)
)
);
int deleteCount = entityManager.createQuery(delete).executeUpdate();
genera esta consulta de eliminación de SQL:
DELETE FROM
post_comment
WHERE
status = 2 AND
updated_on <= '2020-08-06 10:50:43.115'
Por lo tanto, no hay una cascada a nivel de entidad ya que la eliminación se realiza mediante la instrucción SQL, no a través de la EntityManager
.
Eliminación masiva en cascada
Para habilitar la cascada al ejecutar la eliminación masiva, debe usar la cascada de nivel DDL al declarar las restricciones FK.
ALTER TABLE post_comment
ADD CONSTRAINT FK_POST_COMMENT_POST_ID
FOREIGN KEY (post_id) REFERENCES post
ON DELETE CASCADE
Ahora, al ejecutar la siguiente declaración de eliminación masiva:
DELETE FROM
post
WHERE
status = 2 AND
updated_on <= '2020-08-02 10:50:43.109'
La base de datos eliminará el post_comment
registros que hacen referencia a la post
filas que se eliminaron.
La mejor manera de ejecutar DDL es a través de una herramienta de migración de esquema automática, como Flyway, por lo que la definición de clave externa debe residir en un script de migración.
Si está generando los scripts de migración con la herramienta HBM2DLL, entonces, en el PostComment
clase, puede usar la siguiente asignación para generar la declaración DDL mencionada anteriormente:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(foreignKey = @ForeignKey(name = "FK_POST_COMMENT_POST_ID"))
@OnDelete(action = OnDeleteAction.CASCADE)
private Post post;
Si realmente le importa el tiempo que lleva realizar esta eliminación masiva, le sugiero que use JPQL para eliminar sus entidades. Cuando emites un DELETE
Consulta JPQL, emitirá directamente una eliminación en esas entidades sin recuperarlas en primer lugar.
int deletedCount = entityManager.createQuery("DELETE FROM Country").executeUpdate();
Incluso puede hacer eliminaciones condicionales basadas en algunos parámetros en esas entidades usando la API de consulta como se muestra a continuación
Query query = entityManager.createQuery("DELETE FROM Country c
WHERE c.population < :p");
int deletedCount = query.setParameter(p, 100000).executeUpdate();
executeUpdate
devolverá el número de filas eliminadas una vez que se complete la operación.
Si tiene el tipo de cascada adecuado en sus entidades como CascadeType.ALL
(o) CascadeType.REMOVE
entonces la consulta anterior hará el truco por ti.
@Entity
class Employee
@OneToOne(cascade=CascadeType.REMOVE)
private Address address;
Para más detalles, echa un vistazo a esto y esto.
Valoraciones y reseñas
Te invitamos a respaldar nuestra publicación poniendo un comentario y puntuándolo te lo agradecemos.