spring04-transaction
spring 的事务xml配置(事务使用xml配置, 其他的ioc bean使用注解)
- 配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 引用数据源bean --> <property name="dataSource" ref="dataSource"/> </bean>
- 配置事务的通知
<tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" propagation="REQUIRED" read-only="false"/> <tx:method name="get*" propagation="SUPPORTS" read-only="true"/> <tx:method name="find*" propagation="SUPPORTS" read-only="true"/> </tx:attributes> </tx:advice>
- 使用tx:advice标签配置事务通知
- 属性:
- id:事务的唯一标识
- transaction-manager:给事务通知提供一个事务管理器引用
- 属性:
- 使用tx:advice标签配置事务通知
- 配置AOP中的通用切入点表达式
<aop:pointcut id="txPc" expression="execution(* cn.ann.service..*.*(..))"/>
- 建立事务通知和切入点表达式的对应关系
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"/>
- 配置事务的属性
- 使用tx:advice标签内部的tx:attributes标签配置事务属性
<tx:attributes> <tx:method name="*" propagation="REQUIRED" read-only="false"/> <tx:method name="get*" propagation="SUPPORTS" read-only="true"/> <tx:method name="find*" propagation="SUPPORTS" read-only="true"/> </tx:attributes>
- name: 要为什么方法配置事务. * 是通配符
- isolation:用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别。
- propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS
- read-only:用于指定事务是否只读。只有查询方法才能设置为true。默认值是false,表示读写
- timeout:用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值,以秒为单位
- rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值。表示任何异常都回滚
- no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值。表示任何异常都回滚
- 使用tx:advice标签内部的tx:attributes标签配置事务属性
spring 事务的纯注解配置
- 创建需要的bean(数据源, 事务管理器等)
- 在配置类使用注解开启事务管理: @EnableTransactionManagement
- 配置通用切入点表达式:
@Pointcut("execution(* cn.ann.service..*.*(..))") public void txPc(){}
- 为每一个需要配置事务的方法配置事务的属性
@Transactional(propagation = Propagation.REQUIRED, readOnly = false) public void transfer(String source, String target, Double money) { ... } @Transactional(propagation = Propagation.SUPPORTS, readOnly = true) public Account getAccountByName(String name) throws SQLException { ... } @Transactional(propagation = Propagation.SUPPORTS, readOnly = true) public Account getAccountById(Integer id) throws SQLException { ... }
spring 的编程式事务控制
- 创建事务管理器bean
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
- 创建事务模板bean
<bean id="txTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"/> </bean>
- 编写业务代码
@Service("accountService") public class AccountServiceImpl implements AccountService { @Resource(name = "txTemplate") private TransactionTemplate txTemplate; @Resource(name = "accountDao") private AccountDao dao; @Override public void transfer(String source, String target, Double money) { txTemplate.execute(status -> { try { Account sourceAccount = dao.getAccountByName(source); Account targetAccount = dao.getAccountByName(target); sourceAccount.setAccountMoney(sourceAccount.getAccountMoney() - money); dao.updateAccount(sourceAccount); // int i = 1 / 0; targetAccount.setAccountMoney(targetAccount.getAccountMoney() + money); dao.updateAccount(targetAccount); } catch (SQLException e) { e.printStackTrace(); } return null; }); } @Override public Account getAccountById(Integer id) throws SQLException { return txTemplate.execute(status -> { try { return dao.getAccountById(id); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } }); } @Override public Account getAccountByName(String name) throws SQLException { return txTemplate.execute(status -> { try { return dao.getAccountByName(name); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } }); } }
- 在代码中可以看到大量重复的部分: txTemplate.execute. 代码用了lambda表达式, 所以感觉并没有那么"震撼", 因为这个原因, 开发中基本不用编程式事务控制
在开发中, 关于用注解还是配置文件: 在公司没有硬性要求的情况下, 怎么方便怎么来. 我一般用配置文件配置事务
本片代码: 此处 的所有spring04