@RequestMapping(value = "/updateUser")
public void updateUser() {
userservice.updateUser();
}
@Transactional
public void updateUser(){
User user = userMapper.selectByPrimaryKey(1);
user.setUserName("cdd");
userMapper.updateById(user);
int i = 1 / 0;
}
// 回滚
@RequestMapping(value = "/updateUser")
public void updateUser() {
userservice.updateUser();
}
@Transactional
public void updateUser(){
try {
User user = userMapper.selectByPrimaryKey(1);
user.setUserName("cdd");
userMapper.updateById(user);
throw new ClassNotFoundException();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// 不回滚
证明运行时异常会回滚,编译异常不会回滚:
spring aop 异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获runtimeexception的异常,但可以通过
// service中的两个方法在同一个类中
// 第一种
@RequestMapping(value = "/updateUser")
public void updateUser() {
userservice.updateUser();
}
public void updateUser(){
User user = userMapper.selectByPrimaryKey(1);
user.setUserName("cdd");
userMapper.updateById(user);
updateDemo();
}
@Transactional
public void updateDemo(){
User user = userMapper.selectByPrimaryKey(2);
user.setUserName("cdd");
userMapper.updateById(user);
int i = 1 / 0;
}
// 两个方法不回滚
// 第二种
@RequestMapping(value = "/updateUser")
public void updateUser() {
userservice.updateUser();
}
@Transactional
public void updateUser(){
User user = userMapper.selectByPrimaryKey(1);
user.setUserName("cdd");
userMapper.updateById(user);
updateDemo();
}
public void updateDemo(){
User user = userMapper.selectByPrimaryKey(2);
user.setUserName("cdd");
userMapper.updateById(user);
int i = 1 / 0;
}
// 两个方法回滚
// 第三种
@RequestMapping(value = "/updateUser")
public void updateUser() {
userservice.updateUser();
}
@Transactional
public void updateUser(){
User user = userMapper.selectByPrimaryKey(1);
user.setUserName("cdd");
userMapper.updateById(user);
updateDemo();
}
@Transactional
public void updateDemo(){
User user = userMapper.selectByPrimaryKey(2);
user.setUserName("cdd");
userMapper.updateById(user);
int i = 1 / 0;
}
// 两个方法回滚
第一种:Controller调用Service没有事务注解所以没有开启代理,方法内调用本类的有事务注解的方法,因为是同类所以调用的还是原始对象的updateDemo所以没有还是没有走Aop开启使用。
第二三种:Controller调用Service有事务注解开启代理,开启事务,方法内调用本类的方法也是在一个事务内,所以会回滚。
// 把第二个方法移到其他service中
// 第一种
@RequestMapping(value = "/updateUser")
public void updateUser() {
userservice.updateUser();
}
@Resource
private demoservice demo;
public void updateUser(){
User user = userMapper.selectByPrimaryKey(1);
user.setUserName("cdd");
userMapper.updateById(user);
demo.updateDemo();
}
@Transactional
public void updateDemo(){
User user = userMapper.selectByPrimaryKey(2);
user.setUserName("cdd");
userMapper.updateById(user);
int i = 1 / 0;
}
// updateUser不回滚 updateDemo回滚
// 第二种
@RequestMapping(value = "/updateUser")
public void updateUser() {
userservice.updateUser();
}
@Resource
private demoservice demo;
@Transactional
public void updateUser(){
User user = userMapper.selectByPrimaryKey(1);
user.setUserName("cdd");
userMapper.updateById(user);
demo.updateDemo();
}
@Transactional
public void updateDemo(){
User user = userMapper.selectByPrimaryKey(2);
user.setUserName("cdd");
userMapper.updateById(user);
int i = 1 / 0;
}
// updateUser回滚 updateDemo回滚
第一种:Controller调用Service没有事务注解所以没有开启代理,方法内调用另一个类的方法有事务注解开启事务。异常以后回滚,主方法没有事务所以没有回滚。
第二种:Controller调用Service有事务注解所以开启代理开启事务,方法内调用另一个类的方法有事务注解因为默认事务传播机制是PROPAGATION_REQUIRED所以所以加入事务。整体回滚。
以下是事物的传播机制:
@Transactional(propagation=Propagation.REQUIRED)
如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
@Transactional(propagation=Propagation.NOT_SUPPORTED)
容器不为这个方法开启事务
@Transactional(propagation=Propagation.REQUIRES_NEW)
不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
@Transactional(propagation=Propagation.MANDATORY)
必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.NEVER)
必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.SUPPORTS)
如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.