在上篇中,我们发现当Service
层操作Dao
时,发生错误后会使Sql语句出现执行错误问题:用户A增加了100,用户B未执行减少操作。
在该篇,我们将学习Spring的事务操作。(仅仅展示声明式事务)
Spring做事务管理的Bean
回顾:当我们自己手动操作事务的时候需要走这几步:
- 拿到
DataSource
的connection
- 手动设置
connection
的setAutoCommit
为false
,我们需要自己编程控制事务的提交和回滚 - 使用
try...catch
将业务代码包围 - 在
catch
中设置回滚 - 在
finally
设置关闭connection
还挺麻烦的,现在框架的好处体现了,Spring帮我们做了这些事,我们只需要将一个Bean
注入到容器中,管理我们的DataSource
就行。
需要注入的Bean org.springframework.jdbc.datasource.DataSourceTransactionManager
注解篇
这里重点分享如何使用注解,编写声明式事务,因为注解相比其他方式真的太简单了。
编写配置文件
将DataSourceTransactionManager
注入到Spring容器中。在构造方法中只需要把driverManagerDataSource()
通过依赖注入的方式注入。
@Configuration
@ComponentScan("juejin.jdbc.anno")
public class JdbcAnnotationConfig {
@Bean
public DriverManagerDataSource driverManagerDataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/juejin_sql");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate(){
return new JdbcTemplate(driverManagerDataSource());
}
// 这里是新内容
@Bean
public DataSourceTransactionManager dataSourceTransactionManager(){
return new DataSourceTransactionManager(driverManagerDataSource());
}
}
添加@EnableTransactionManagement
注解
@Configuration
@ComponentScan("juejin.jdbc.anno")
// 这里是新内容
@EnableTransactionManagement
public class JdbcAnnotationConfig
在具体的业务上添加@Transactional
注解
这里我们在业务AccountService
上添加了@Transactional
注解,表示该类中所有的方法都开启了事务。
@Service
@Transactional
public class AccountService {
@Autowired
AccountDao accountDao;
// 一个交易方法
public void deal(){
accountDao.addMoney(1,100);
int i = 1 / 0;
accountDao.reduceMoney(2,100);
}
}
测试
结果:数据库中的数据是正常的,表示SQL事务控制成功。
public class JdbcAnnotationApplication {
public static void main(String[] args) throws SQLException {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JdbcAnnotationConfig.class);
AccountService service = ctx.getBean(AccountService.class);
service.deal();
}
}