use*_*383 4 java jpa eclipselink jpa-2.1
我正在尝试在我的实体中进行批量删除,我认为最好的解决方案就是一起去CriteriaDelete
.但是CriteriaDelete
没有级联(至少不适合我).
所以似乎只有我要做的解决方案是先选择,然后单独删除每个元素.这对我来说似乎没有错.
有人有更好的想法如何批量删除?它真的更好吗?
如果它有助于我使用eclipselink 2.5.2.
选项是:
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)