项目环境:spring boot+JPA+MySQL,JDK1.8

deleteById

根据主键id删除,最为普遍的用法,由JPA提供的方法,无需在repository层声明,也无需加事物注解 @Transactional

    @Override
    public void delete(String id) {
        studentRepository.deleteById(id);
    }

deleteByXXX

根据XXX删除,需要在repository层声明,也需在service层方法加事物注解 @Transactional

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByName(String name) {
        studentRepository.deleteByName(name);
    }

先delete后add

需求:根据”name“删除一条数据后、再新增一条数据,并且数据库中”name“是有唯一性约束的
错误代码:

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAndAdd(Student student) {
        studentRepository.deleteByName(student.getName());
        studentRepository.save(student);
    }

问题:
在这里插入图片描述
错误输出日志中已说明:由数据库唯一性约束导致。
原因分析:
输出JPA的sql执行语句看看:在这里插入图片描述
很明显,并未做删除操作,就执行了插入操作,所以出现”name“重复的情况
从网上找答案:

jpa是在整个事务完了之后再执行delete语句的。 通常,一个实体在被删除之前必须进行管理,因此JPA提供程序将首先加载(您看到的查询)该实体,然后发出删除。

我的理解是,delete操作是在deleteAndAdd()方法执行完毕后才执行(这里不确定)
两种解决办法:

  • 调用flush()方法
   @Override
   @Transactional(rollbackFor = Exception.class)
   public void deleteAndAdd(Student student) {
       studentRepository.deleteByName(student.getName());
       studentRepository.flush();
       studentRepository.save(student);
   }

在这里插入图片描述

  • 在Repository层使用jpql语句
@Repository
public interface StudentRepository extends BaseRepository<Student, String> {
    /**
     * 根据姓名删除学生
     * @param name 学生姓名
     */
    @Modifying
    @Query(value = "delete from Student s where s.name = :name")
    void deleteByName(@Param String name);
}

在这里插入图片描述

Logo

更多推荐