当前位置: 首页 > wzjs >正文

潍坊中脉网站建设无锡网站设计公司电话

潍坊中脉网站建设,无锡网站设计公司电话,中国纪检监察报杂志,wordpress ssl 500概述 在使用Spring Boot JPA时,执行批量删除操作时,遇到逻辑删除失效的问题。具体而言,当使用deleteAllInBatch方法时,数据会被物理删除,而不是进行逻辑删除;但是当使用deleteAll时,逻辑删除操…

概述

在使用Spring Boot JPA时,执行批量删除操作时,遇到逻辑删除失效的问题。具体而言,当使用deleteAllInBatch方法时,数据会被物理删除,而不是进行逻辑删除;但是当使用deleteAll时,逻辑删除操作可以正常生效。经过调查,发现deleteAllInBatch方法和deleteAll方法的行为有所不同,导致逻辑删除失败。

症状

  • 使用deleteAllInBatch方法时,数据直接从数据库中物理删除。
  • 使用deleteAll方法时,逻辑删除生效,数据并未被物理删除,而是更新了delLogic字段。

使用的实体类代码

@Entity
public class TemplateField {@Idprivate Long id;private Integer delLogic;  // 用于标记是否被逻辑删除@PreRemovepublic void templateField() {this.setDelLogic(1);  // 设置逻辑删除标记}@SQLDelete(sql = "UPDATE t_template_field SET del_logic = 1 WHERE id = ?")@Where(clause = "del_logic = 0")  // 过滤删除标记为0的数据public void setDelLogic(Integer delLogic) {this.delLogic = delLogic;}
}

问题原因

问题的根本原因是deleteAllInBatchdeleteAll在执行删除操作时的实现方式不同,导致生命周期回调方法(如@PreRemove)未被触发。

deleteAllInBatchdeleteAll的区别

  1. deleteAll():该方法会逐个加载实体,并在JPA上下文中处理每个实体的删除操作。每次删除实体时,都会触发实体的生命周期回调方法(如@PreRemove@PostRemove等)。因此,当使用deleteAll()方法时,你在实体类上定义的逻辑删除(例如通过@PreRemove标记设置删除标记)可以生效。

  2. deleteAllInBatch():该方法是一个批量删除操作,通常是直接生成SQL语句一次性删除数据,不会逐个加载实体,因此也不会触发实体的生命周期回调方法。批量操作的优势在于效率较高,但缺点是无法触发与实体相关的生命周期事件,如@PreRemove@PostRemove

deleteAllInBatch导致物理删除的原因

deleteAllInBatch()方法并不会按@PreRemove中的逻辑设置delLogic字段,而是直接执行数据库的物理删除操作。这就是为什么在使用deleteAllInBatch()时,数据会被直接从数据库中删除,而不是进行逻辑删除的原因。


问题解决方案

要解决这个问题,通常有以下几种方式:

方案 1:使用deleteAll()替代deleteAllInBatch()

如果逻辑删除的需求比性能更为重要,并且不介意性能稍微下降,可以直接使用deleteAll()方法。这会逐个处理实体,并触发相应的生命周期回调方法,从而确保逻辑删除(即更新delLogic字段)生效。

方案 2:自定义批量更新方法

如果依然希望使用批量删除操作(如deleteAllInBatch()),可以自定义一个批量更新的方法,通过直接执行SQL更新操作来实现逻辑删除。这种方式可以保证批量操作时的效率,同时避免物理删除数据。

例如,使用@Modifying@Query注解,执行批量更新操作:

@Modifying
@Query("UPDATE TemplateField tf SET tf.delLogic = 1 WHERE tf.id IN :ids")
int batchLogicalDelete(@Param("ids") List<Long> ids);

该方法会直接更新符合条件的记录,将delLogic字段设置为1,达到逻辑删除的效果。

方案 3:手动更新实体后再执行批量删除

可以先通过查询获取所有需要“删除”的实体,将它们的delLogic字段设置为逻辑删除标志,然后再调用deleteAllInBatch()进行删除操作。

代码示例:

List<TemplateField> fields = templateFieldRepository.findAllById(ids);
fields.forEach(field -> field.setDelLogic(1));  // 更新逻辑删除标志
templateFieldRepository.saveAll(fields);  // 保存更新
templateFieldRepository.deleteAllInBatch(fields);  // 执行批量删除

这种方式在批量删除前,先手动更新实体,确保逻辑删除字段被正确设置。


问题示例代码

使用deleteAll()进行逻辑删除

List<TemplateField> fields = templateFieldRepository.findAllById(ids);
fields.forEach(field -> field.setDelLogic(1));  // 更新逻辑删除标志
templateFieldRepository.saveAll(fields);  // 保存更新
templateFieldRepository.deleteAll(fields);  // 执行逐个删除(触发生命周期方法)

自定义批量更新方法进行逻辑删除

@Modifying
@Query("UPDATE TemplateField tf SET tf.delLogic = 1 WHERE tf.id IN :ids")
int batchLogicalDelete(@Param("ids") List<Long> ids);// 调用自定义批量逻辑删除方法
templateFieldRepository.batchLogicalDelete(ids);

手动更新实体后再执行批量删除

List<TemplateField> fields = templateFieldRepository.findAllById(ids);
fields.forEach(field -> field.setDelLogic(1));  // 更新逻辑删除标志
templateFieldRepository.saveAll(fields);  // 保存更新
templateFieldRepository.deleteAllInBatch(fields);  // 执行批量删除

总结

  • deleteAllInBatch()方法直接执行SQL批量删除,不会触发实体的生命周期回调方法(如@PreRemove),导致逻辑删除无效。
  • 如果需要触发回调方法,可以使用deleteAll(),但会影响性能。
  • 也可以自定义批量逻辑删除方法,通过直接更新delLogic字段来避免物理删除。
http://www.dtcms.com/wzjs/603341.html

相关文章:

  • 内网网站建设所需硬件设备电商类网站怎么做推广
  • 补习吧 一家专门做家教的网站青岛建设厅网站
  • 做外贸哪个网站最好中国企业500强搜索版
  • 黄石下陆区建设局网站怎么把平台推广出去
  • 教学资源系统网站建设方案重庆在线网站推广
  • 章丘区当地网站建设哪家好wordpress 分享文章标题
  • 高州网站建设全国企业信息系统网官网
  • 设计好看的网站哈尔滨百度优化
  • 海南省建设人力资源网站科技型中小企业认定条件
  • 网页制作购物网站wordpress md5解密
  • 罗琳做的网站读后感页面设计模板
  • 河南做网站最好的公司网站建设管理的建议
  • 做网站的素材都在哪里下载电商网站代码
  • 网站工程师是做什么的工作励志的句子 正能量
  • 通辽做网站制作环翠区网站建设
  • 企业只有建立了自己的网站长春网络网站制作开发
  • 黄岐建网站如何查看一个网站流量
  • 北京建设部网站如何刷网站排名
  • wordpress网站导入数据库网页设计实训总结3000字大学篇
  • ih5做pc 网站推广自身网站
  • 惠阳住房与规划建设局网站香奈儿电子商务网站建设策划书
  • 唐山cms模板建站网站建设郑州
  • 团队建设网站网站设计类论文怎么做
  • 优秀网站设计推荐宜州设计公司
  • 是想建个网站 用本地做服务器网站的商桥怎么做
  • 宁波seo是什么意思搜索引擎优化的核心是
  • 两个路由器做双网站网站建设费会计账务处理
  • 微信网页网站怎么做软件工程课程网站开发
  • 网站常见结构有那些专业做网站建设设计
  • 做网站给文件不侵权麦云短链接