创建 dao 层
@Repository
public class AccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void save() {
jdbcTemplate.execute("INSERT INTO `mp`.`user`(`id`, `name`, `age`, `email`, `manager_id`, `create_time`, `update_time`, `version`, `deleted`) VALUES (777777, 'doudou', 40, 'boss@baomidou.com', NULL, 20190111142020, NULL, 1, 0);");
}
}
创建 service 层
@Service
public class AccountService {
@Autowired
private AccountDao accountDao;
@Transactional
public void save() {
accountDao.save();
String str = null;
str.length();
}
}
创建事物配置文件
@Configuration
@ComponentScan("com.user.service")
@EnableTransactionManagement // 开启事物管理
public class TxConfig {
/**
* 数据源
*/
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUsername("root");
dataSource.setPassword("123456");
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
//dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/mp");
return dataSource;
}
/**
* jdbc template
*/
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
/**
* 平台事物管理
*/
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
启动类
public class TxMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TxConfig.class);
AccountService accountService = (AccountService) applicationContext.getBean("accountService");
accountService.save();
applicationContext.close();
}
}
具体场景参考第一张图
1.代码入口
2.spring 事物由 aop 实现,所以方法调用会走代理
3.调用父类 proceed() 方法
4.aop 代理对象调用,调用 TransactionInterceptor 的 invoke()
5.调用事物拦截器,调用 TransactionAspectSupport 的 invokeWithinTransaction 处理事物
6.事物处理核心逻辑
判断事务是否开启、创建事物、目标方法执行、事务回滚、事务提交
1.getTransactionAttribute(),关注获取事务配置的方法 computeTransactionAttribute()
2.重点:private 事物不生效原因
通过位与计算,判断是否为 Public,对应的几类修饰符如下:
PUBLIC: 1
PRIVATE: 2
PROTECTED: 4
1.回滚入口
2.重点,事物是否生效判断
3.进入 rollbackOn() 方法,判断该异常是否能进行回滚,这个需要判断主方法抛出的 Exception() 异常,是否在 @Transactional 的配置中
4.getDepth() 看一下异常规则匹配逻辑
5.默认捕获异常