jpa中批量删除的最佳做法是什么

use*_*383 4 java jpa eclipselink jpa-2.1

我正在尝试在我的实体中进行批量删除,我认为最好的解决方案就是一起去CriteriaDelete.但是CriteriaDelete没有级联(至少不适合我).

所以似乎只有我要做的解决方案是先选择,然后单独删除每个元素.这对我来说似乎没有错.

有人有更好的想法如何批量删除?它真的更好吗?

如果它有助于我使用eclipselink 2.5.2.

Chr*_*ris 8

选项是:

  1. 使用cascade.Remove设置映射,加载实体并在每个上调用em.remove
  2. 在主实体上使用批量删除并设置"ON DELETE CASCADE"数据库选项,以便数据库为您级联删除.EclipseLink有一个@CascadeOnDelete注释,让它知道在关系上设置"ON DELETE CASCADE",或者如果使用JPA生成DDL则创建它:http://eclipse.org/eclipselink/documentation/2.5/jpa/extensions /a_cascadeondelete.htm
  3. 在删除主实体之前,使用多个批量删除来删除可能引用的子项.例如:"删除FROM Child c,其中c.parent =(从父P中选择p,其中[delete-conditions])"和"Delete FROM Parent p where [delete-conditions]"参见http://的 10.2.4节docs.oracle.com/middleware/1212/toplink/OTLCG/queries.htm#OTLCG94370了解详情.


Vla*_*cea 6

JPA CriteriaDelete 如何工作

JPACriteriaDelete语句生成 JPQL 批量删除语句,该语句被解析为 SQL 批量删除语句。

因此,以下 JPACriteriaDelete语句:

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    
CriteriaDelete<PostComment> delete = builder.createCriteriaDelete(PostComment.class);

Root<T> 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();
Run Code Online (Sandbox Code Playgroud)

生成此 SQL 删除查询:

DELETE FROM
    post_comment
WHERE
    status = 2 AND
    updated_on <= '2020-08-06 10:50:43.115'
Run Code Online (Sandbox Code Playgroud)

因此,没有实体级级联,因为删除是使用 SQL 语句完成的,而不是通过EntityManager.

批量删除级联

要在执行批量删除时启用级联,您需要在声明 FK 约束时使用 DDL 级级联。

ALTER TABLE post_comment 
ADD CONSTRAINT FK_POST_COMMENT_POST_ID
FOREIGN KEY (post_id) REFERENCES post 
ON DELETE CASCADE
Run Code Online (Sandbox Code Playgroud)

现在,当执行以下批量删除语句时:

DELETE FROM
    post
WHERE
    status = 2 AND
    updated_on <= '2020-08-02 10:50:43.109'
Run Code Online (Sandbox Code Playgroud)

DB 将删除post_comment引用post已删除行的记录。

执行 DDL 的最佳方法是通过自动模式迁移工具,如Flyway,因此外键定义应驻留在迁移脚本中。

如果您使用 HBM2DLL 工具生成迁移脚本,那么在PostComment类中,您可以使用以下映射来生成上述 DDL 语句:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(foreignKey = @ForeignKey(name = "FK_POST_COMMENT_POST_ID"))
@OnDelete(action = OnDeleteAction.CASCADE)
private Post post;
Run Code Online (Sandbox Code Playgroud)