3.2 Spring Boot 事务支持
一般事务只跟DML语句有关系,并且事务的编写一般写在业务层(service)
3.2.1小实验
在开始学习了解Springboot支持之前,我们先做一个小实验,就拿之前通过Mybaties逆向工程生成的项目做即可
在控制层编写StudentController类,代码如下:
@RestController
public class StudentController {
@Autowired
private StudentService studentService;
@RequestMapping(value = "/update")
public Object update(Integer id, String studentName) {
Student student = new Student();
student.setId(id);
student.setStuName(studentName);
int modefyCount = studentService.modifyStudentById(student);
return "修改的结果:" + modefyCount;
}
@RequestMapping(value = "/student/details")
public Object studentDetail(Integer id){
Student student = studentService.queryStudentById(id);
return student;
}
}
上面代码提供两个接口,update表示接收前端传来的id以及studentName,实例化一个Student对象,根据该对象改变对应id的name值,student/details表示根据id查看对应学生的信息
在业务层编写接口:
public interface StudentService {
/*
* 根据学生id获取学生详情
* */
Student queryStudentById(Integer id);
/**
* 根据student对象更新学生信息
* @param student
* @return
*/
int modifyStudentById(Student student);
}
对应实现类:
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentMapper studentMapper;
@Override
public Student queryStudentById(Integer id) {
return studentMapper.selectByPrimaryKey(id);
}
@Override
public int modifyStudentById(Student student){
int modefyCount = studentMapper.updateByPrimaryKeySelective(student);
int a = 10/0;
return modefyCount;
}
}
实现类通过调用逆向工程生成的方法去对数据库进行操作
如果一位开发者稍有细心,会发现modifyStudentById方法中有一处异常: int a = 10/0,当代码运行到这一句时,java会抛出这个错误:java.lang.ArithmeticException: / by zero 。这就引出了下面的问题:
当我们进行某项事务到一半,却因为某些异常或其他原因意外导致事务没有完整地完成,这个时候,如果我们仍然默许事务执行前半部分,这无疑就破坏了事务的原子性,同时也会产生数据层面的混乱,明明不该改变的数据却改变了,这是不应该被我们允许的。
此时出现了错误页面:
但是数据依然被修改了:
可以看到虽然后端报出了错误,但是却依旧执行了数据的update操作。
3.2.2 Springboot的事务支持
Springboot提供了事务支持,保证事务具有原子性,其底层依然采用的是 Spring 本身提供的事务管理
在业务层的实现类方法上添加注解 @Transactional
我们为service层的实现类代码添加注解:
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentMapper studentMapper;
@Transactional
@Override
public Student queryStudentById(Integer id) {
return studentMapper.selectByPrimaryKey(id);
}
@Transactional
@Override
public int modifyStudentById(Student student){
int modefyCount = studentMapper.updateByPrimaryKeySelective(student);
int a = 10/0;
return modefyCount;
}
}
编译测试
可以看到报错了:
但是数据库的数据并没有改变:
入口类中的 @EnableTransactionManagement
在有些项目的后端我们还会看到在注解类里面加上了这么一个注解:@EnableTransactionManagement
@SpringBootApplication
@EnableTransactionManagement
public class SpringbootWorkspaceApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootWorkspaceApplication.class, args);
}
}
该注解属于可选项,事实上Springboot对于事务的支持依靠@Transactional注解来实现,所以只需要使用@Transactional注解就可。
下一篇博客:
Springboot中的MVC