jpa批量删除数据_SpringBoot2Jpa批量删除功能的实现
前台处理
⾸先前台先要获取所有的要删除数据的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 类型
List LString = new ArrayList();
for(String str : stuList){
LString.add(new Integer(str));
}
// 调⽤service层的批量删除函数
studentsService.deleteBatch(LString);
return Msg.success().add("数组", LString);
}
service层
批量更新sql语句@Override
public void deleteBatch(List stuList) {
// 第⼀种批量删除⽅法,是通过spring data中继承JpaRepository接⼝后,通过关键字拼接的⽅法进⾏删除,删除时候是通过ID⼀条⼀条删除的
// studentsRepository.deleteStudentsByStuIdIn(stuList);
// 第⼆种批量删除⽅法, 是通过⾃定义JPQL语句进⾏删除,使⽤的是 where stuId in ()的操作
studentsRepository.deleteBatch(stuList);
}
Repository接⼝层
public interface StudentsRepository extends Repository, JpaRepository {
/**
* @function ⾃定义JPQL
* @param ids
*/
// 注意更新和删除是需要加事务的, 并且要加上 @Modify的注解
@Modifying
@Transactional
@Query("delete from Students s where s.stuId in (?1)")
void deleteBatch(List ids);
// 这个是通过spring data拼接关键字进⾏的操作
void deleteStudentsByStuIdIn(List 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 entities)
/**
点进源码 看看。
org.springframework.pository.support.SimpleJpaRepository#deleteInBatch
*/
@Transactional
public void deleteInBatch(Iterable entities) {
if (!entities.iterator().hasNext()) {
return;
}
// 继续跟踪
applyAndBind(getQueryString(DELETE_ALL_QUERY_STRING, EntityName()), entities, em) .executeUpdate();
}
/**
org.springframework.pository.query.QueryUtils#applyAndBind
*/
public static Query applyAndBind(String queryString, Iterable 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()) {
<();
builder.append(String.format(" %s = ?%d", alias, ++i));
if (iterator.hasNext()) {
builder.append(" or");
}
}
Query query = String());
iterator = entities.iterator();
i = 0;
while (iterator.hasNext()) {
query.setParameter(++i, ());
}
}
结合⽇志记录的错误信息,进⼊到org.hibernate.hql.internal.antlr.HqlSqlBaseWalker#logicalExpr ⽅法
下⾯贴⼀下调⽤栈
org.hibernate.hql.internal.antlr.HqlSqlBaseWalker#deleteStatement ⽅法中 whereClause()调⽤到了logicalExpr ⽅法。由下图可知,该⽅法在①处递归调⽤⾃⾝,会不断的创建栈帧,当超出栈深度或者超出栈的⼤⼩后,会爆出 栈溢出。
⾄于① 处怎么跳出继续执⾏后⾯的代码,还没研究,有知道的⼩伙伴请指教,不正确的地⽅也请指正。
以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持脚本之家。如有错误或未考虑完全的地⽅,望不吝赐教。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论