声明式事务
概述
编程式事务:
TransactionFilter{
try{
//获取连接
//设置非自动提交
chain.doFilter();
//提交
}catch{
//事务回滚
}finally{
//关闭连接释放资源
}
}
或使用AOP环绕通知
//获取连接
//设置非自动提交
目标代码执行
//正常提交
//异常回滚
//最终关闭
声明式事务:
现在只需要将事务方法利用注解标记出来即可
事务管理代码的固定模式作为一种横切关注点,可以通过AOP方法模块化,进而借助SpringAOP框架实现声明式事务管理
Spring自身提供了该事务切面(事务管理器)
目前使用DataSourceTransactionManager,该事务管理器可以在目标方法运行前后进行事务控制
使用
- 环境搭建
dao
@Repository
public class BookDao {
@Autowired
private JdbcTemplate jdbcTemplate;
//1. 修改余额
public void updateBalance(String username,int price){
String sql = "UPDATE account SET balance=balance-? WHERE username=?";
jdbcTemplate.update(sql,price,username);
}
//2. 按照图书的ISBN获取某本图书的价格
public int getPrice(String isbn){
String sql = "SELECT price FROM book WHERE isbn=?";
return jdbcTemplate.queryForObject(sql,Integer.class,isbn);
}
//3. 修改库存,每次将书本库存减少一
public void updateStock(String isbn){
String sql = "UPDATE book_stock SET stock=stock-1 WHERE isbn=?";
jdbcTemplate.update(sql,isbn);
}
//4. 修改图书价格
public void updatePrice(String isbn,int price){
String sql = "update book set price=? where isbn=?";
jdbcTemplate.update(sql,price,isbn);
}
}
service
@Service
public class BookService {
@Autowired
private BookDao bookDao;
//结账,传入哪个顾客购买了哪本书
public void checkout(String username,String isbn){
//1. 修改库存
bookDao.updateStock(isbn);
//2. 获取书本价格
int price = bookDao.getPrice(isbn);
//3. 修改用户余额
bookDao.updateBalance(username,price);
}
}
- 快速为某个方法添加事务
1)配置事务管理器
2)开启基于注解的事务
3)给事务方法添加@Transactional注解
<context:component-scan base-package="com.th1024"></context:component-scan>
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="name" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
</bean>
<!--配置JdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>
<!--
事务控制
配置事务管理器(切面)让其进行事务控制,导入jar包
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-aspects-5.2.6.RELEASE.jar
-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--1. 注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--2. 开启基于注解的事务控制模式,依赖tx名称空间-->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!--3. 给事务方法添加注解@Transactional-->
@Service
public class BookService {
@Autowired
private BookDao bookDao;
//结账,传入哪个顾客购买了哪本书
@Transactional(propagation = Propagation.REQUIRES_NEW) //添加事务控制注解
public void checkout(String username,String isbn){
//1. 修改库存
bookDao.updateStock(isbn);
//2. 获取书本价格
int price = bookDao.getPrice(isbn);
//模拟网络阻塞
// int i = 10/0;
//3. 修改用户余额
bookDao.updateBalance(username,price);
}
}
测试
public class TxTest {
ApplicationContext ioc = new ClassPathXmlApplicationContext("tx.xml");
@Test
public void test1(){
BookService bookService = ioc.getBean(BookService.class);
bookService.checkout("Tom","ISBN-001");
}
}