SpringBoot2 Jpa 批量删除功能的实现
作者:易水墨龙吟 发布时间:2023-06-18 04:54:35
前台处理
首先前台先要获取所有的要删除数据的ID,并将ID拼接成字符串 例如: 2,3,4,5,然后通过GET请求返送到后台。
后台处理
控制器接收
/**
* @function 批量删除
* @param stu_id
* @return
*/
@GetMapping("/del_stu")
@ResponseBody
public Msg batch_del_stu(@RequestParam("stu_id") String stu_id){
// 接收包含stuId的字符串,并将它分割成字符串数组
String[] stuList = stu_id.split(",");
// 将字符串数组转为List<Intger> 类型
List<Integer> LString = new ArrayList<Integer>();
for(String str : stuList){
LString.add(new Integer(str));
}
// 调用service层的批量删除函数
studentsService.deleteBatch(LString);
return Msg.success().add("数组", LString);
}
service层
@Override
public void deleteBatch(List<Integer> stuList) {
// 第一种批量删除方法,是通过spring data中继承JpaRepository接口后,通过关键字拼接的方法进行删除,删除时候是通过ID一条一条删除的
// studentsRepository.deleteStudentsByStuIdIn(stuList);
// 第二种批量删除方法, 是通过自定义JPQL语句进行删除,使用的是 where stuId in ()的操作
studentsRepository.deleteBatch(stuList);
}
Repository接口层
public interface StudentsRepository extends Repository<Students, Integer>, JpaRepository<Students, Integer> {
/**
* @function 自定义JPQL
* @param ids
*/
// 注意更新和删除是需要加事务的, 并且要加上 @Modify的注解
@Modifying
@Transactional
@Query("delete from Students s where s.stuId in (?1)")
void deleteBatch(List<Integer> ids);
// 这个是通过spring data拼接关键字进行的操作
void deleteStudentsByStuIdIn(List<Integer> ids);
}
附加
@Modifying注解
1、在@Query注解中编写JPQL实现DELETE和UPDATE操作时候必须加上@Modifying注解,通知Spring Data这是一个delete或者updata操作
2、 updata和delete操作需要使用事务,此时需要定义service层,在service方法上添加事务操作
3、 注意JPQL不支持insert操作
@Query 如果在注解中添加 nativeQuery=true 是支持原生SQL查询
补充:SpringJPA 批量删除引起的StackOverFlow
项目里有一处根据Id,批量删除一些历史数据的代码(xxxRepository.deleteInBatch(list);),发现传入list过大时,出现栈溢出(StackOverFlowError) 。
解决方法:
list切分成多份,循环批量删除。
下面是简单的了解一下执行流程。
deleteInBatch(Iterable<T> entities)
/**
点进源码 看看。
org.springframework.data.jpa.repository.support.SimpleJpaRepository#deleteInBatch
*/
@Transactional
public void deleteInBatch(Iterable<T> entities) {
Assert.notNull(entities, "The given Iterable of entities not be null!");
if (!entities.iterator().hasNext()) {
return;
}
// 继续跟踪
applyAndBind(getQueryString(DELETE_ALL_QUERY_STRING, entityInformation.getEntityName()), entities, em)
.executeUpdate();
}
/**
org.springframework.data.jpa.repository.query.QueryUtils#applyAndBind
*/
public static <T> Query applyAndBind(String queryString, Iterable<T> entities, EntityManager entityManager) {
// ... 省略一些code
// 最后会形成 delete from xx表 x(表别名) where x.id =? or x.id=?... 一条sql语句
String alias = detectAlias(queryString);
StringBuilder builder = new StringBuilder(queryString);
builder.append(" where");
int i = 0;
while (iterator.hasNext()) {
iterator.next();
builder.append(String.format(" %s = ?%d", alias, ++i));
if (iterator.hasNext()) {
builder.append(" or");
}
}
Query query = entityManager.createQuery(builder.toString());
iterator = entities.iterator();
i = 0;
while (iterator.hasNext()) {
query.setParameter(++i, iterator.next());
}
}
结合日志记录的错误信息,进入到org.hibernate.hql.internal.antlr.HqlSqlBaseWalker#logicalExpr 方法
下面贴一下调用栈
org.hibernate.hql.internal.antlr.HqlSqlBaseWalker#deleteStatement 方法中 whereClause()调用到了logicalExpr 方法。
由下图可知,该方法在①处递归调用自身,会不断的创建栈帧,当超出栈深度或者超出栈的大小后,会爆出 栈溢出。
至于① 处怎么跳出继续执行后面的代码,还没研究,有知道的小伙伴请指教,不正确的地方也请指正。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。
来源:https://blog.csdn.net/yhflyl/article/details/81557670


猜你喜欢
- 本文实例为大家分享了Android App获取屏幕旋转角度的具体代码,供大家参考,具体内容如下一、获取屏幕旋转角度的方法是:int rota
- 第 1 步:将这个 Spring Boot 项目的打包方式设置为 war。<packaging>war</packagin
- 几个月前写过一篇博客《xUtils3.0框架学习笔记》 ,上面也有记录通过xUtils实现文件上传的使用方法,代码如下:private vo
- 自然排序TreeSet集合在存储数据时有一定的顺序,它会将一些数据进行比较,比较调用的是comparaTo()方法,该方法是在Compara
- EasyPoi 多sheet导出序言:之前一直想开始写博客,都没有时间行动起来,今天终于开始了我的第一篇博客…最近接到一个导出excel功能
- 1.导入jar包: <!--jmsTemplate--> <dependency> <
- 背景在实际开发过程中,会遇到需要编写各类打印模板模板的需求,当然这些在WPF开发中更为常见,但是使用XAML写编辑的打印模板又不能直接发送给
- Web Fragment 是什么 - 它是在 servlet 3.0开始支持的,可以把一个dy web项目拆分为多个项目,解耦合,使其在项目
- 摘要今天用compose来构建一个气泡上升粘连动画和水滴下坠动画,Github源码点击这里知识点compose动画贝塞尔曲线缓动函数comp
- JavaFx中其实也可以直接使用字体图标iconfont的,只需要加载ttf字体文件,之后设置unicode即可,具体可以看我给出的代码既然
- 前言数据库存储是我们常用的存储方式之一,对大批量数据有增、删、改、查操作需求时,我们就会想到使用数据库,Flutter中提供了一个sqfli
- 最近做项目有这样的需求: 在activity中启动一个dialog时, 启动的dialog的背景设为启动acitivity的模糊化图片.实现
- SpringBoot配置外部静态资源映射使用场景实际项目中,特别是前后端分离的项目,SpringBoot后台打包(jar包)后,以jar包形
- 本文实例分析了C#实现的24点游戏。分享给大家供大家参考。具体如下:1. 24点游戏规则及算法规则:给出4个自然数,找出能够求出24的四则运
- Android 中 ActivityLifecycleCallbacks的实例详解  
- java 在Jetty9中使用HttpSessionListener和FilterHttpSessionListener当Session创建
- 继承反应了类和类之间的关系。世界上很多事物都是有共性的,共性的那一部分我们就抽象为基类,用于派生其它类,这样提高了代码的复用性,使得代码的结
- 前言最近在学习java8,所以接下来会给大家介绍一系列的Java8学习内容,那么让我们先从lambda表达式开始。众所周知从java8出现以
- 直译过来就是倒计数(CountDown)门闩(Latch)。倒计数不用说,门闩的意思顾名思义就是阻止前进。在这里就是指 CountDownL
- 阿里终面在线编程题,写出来与大家分享一下 有一个单向链表