Spring中的事务传播机制
spring中的事务传播机制之前一直不是很懂,这次整理了一下,对于难理解的三种传播机制做了比较分析,这三个在项目中还是比较常用的,建议理解消化,对比记忆。下面先把整理好的表格放上来。主要应对的三种情况的异常:外层正常try-catch内层,内层出错;外层正常,内层出错,外层不try-catch;外层出错,内层正常。
下面我把测试代码块放上来
目录结构
数据库表结构
TestMapper
package com.example.demo.mapper;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import java.util.Map;
@Mapper
public interface TestMapper {
@Insert("insert into users(username,password,department) values(#{username},#{password},#{department})")
void register(Map<String, Object> params);
}
InnerServiceImpl
package com.example.demo.service;
import com.example.demo.mapper.TestMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.Map;
@Service
@Transactional(propagation = Propagation.NESTED)
public class InnerServiceImpl implements InnerService {
@Autowired
TestMapper testMapper;
@Override
public void test() throws Exception {
Map<String,Object> params = new HashMap<>();
params.put("username","inner");
params.put("password","sd");
params.put("department","s212");
testMapper.register(params);
throw new RuntimeException("错误了");
}
@Override
public void test2() {
Map<String,Object> params = new HashMap<>();
params.put("username","inner");
params.put("password","sd");
params.put("department","s212");
testMapper.register(params);
}
}
TestServiceImpl
package com.example.demo.service;
import com.example.demo.mapper.TestMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.Map;
@Service
@Transactional(propagation = Propagation.NESTED)
public class TestServiceImpl implements TestService {
@Autowired
InnerService innerService;
@Autowired
TestMapper testMapper;
@Override
public void t2() throws Exception {
Map<String,Object> params = new HashMap<>();
params.put("username","outer");
params.put("password","sd");
params.put("department","s212");
testMapper.register(params);
innerService.test();
}
@Override
public void t3() {
Map<String,Object> params = new HashMap<>();
params.put("username","outer");
params.put("password","sd");
params.put("department","s212");
testMapper.register(params);
try {
innerService.test();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void t4() throws Exception {
Map<String,Object> params = new HashMap<>();
params.put("username","outer");
params.put("password","sd");
params.put("department","s212");
testMapper.register(params);
innerService.test2();
throw new RuntimeException("外层出错");
}
}
测试用例
package com.example.demo;
import com.example.demo.service.TestService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Demo7ApplicationTests {
@Autowired
TestService testService;
@Test
void contextLoads() throws Exception {
// testService.t2(); // 测试内层报错
// testService.t3(); // 测试内层报错,外层try catch
testService.t4(); // 测试外层报错
}
}
修改InnerServiceImpl中@Transactional(propagation = Propagation.NESTED)分别为Propagation.REQUIRED,Propagation.REQUIRE_NEW,然后用测试中的三个方法分别进行测试。查看数据库中的数据,进行分析,就可以得到表格中的结果。