1.声明式事务:以前都是通过编程式事务,现在则只需要告诉Spring哪些是声明式事务即可
事务管理代码的固定模式作为一种横切关注点,可以通过AOP方法模块化,进而借助AOP框架实现声明式事务管理。
对于事务管理的方法(切面方法)不需要自己写,Spring会提供事务切面(事务管理器)
2.ResourceTransactionManager为一个接口,其子类中根据不同的框架选择不同的事务管理器
该事务管理器可以在目标方法前后进行事务控制。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<context:component-scan base-package="com.cuco"></context:component-scan>
<!-- 加载外部配置文件 固定写法classpath:表示引用类路径下的配置文件 -->
<context:property-placeholder location="classpath:dbconfig.properties"/>
<bean id="poolDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- ${}表示的就是动态取出配置文件中的value值 -->
<!-- 为了防止配置文件中的username和Spring中的属性值username冲突,因此将配置文件中的key值加上前缀 -->
<property name="user" value="${jdbc.username}" ></property>
<property name="password" value="${jdbc.password}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
</bean>
<bean class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="poolDataSource"></property>
</bean>
<!-- 事务控制 -->
<!-- 1.配置事务管理器让其进行事务控制 -->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 控制数据源 -->
<property name="dataSource" ref="poolDataSource"></property>
</bean>
<!-- 开启基于注解的事务控制模式:依赖tx名称空间 -->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
<!-- 给事务方法加注解 -->
</beans>
@Service
public class BookService {
@Autowired
BookDao bookDao;
@Transactional
public void checkout(String username,String isbn){
bookDao.updateStock(isbn);
bookDao.updateBalance(username,bookDao.getPrice(isbn));
}
}
@Repository
public class BookDao {
@Autowired
JdbcTemplate jdbcTemplate;
//减账户余额
public void updateBalance(String userName,int price){
String sql = "UPDATE account SET balance=balance-? WHERE username=?";
jdbcTemplate.update(sql, price,userName);
}
//获取某本图书的价格
public int getPrice(String isbn){
String sql = "SELECT price FROM book WHERE isbn=?";
return jdbcTemplate.queryForObject(sql, Integer.class,isbn);
}
//减库存
public void updateStock(String isbn){
String sql = "UPDATE book_stock SET stock=stock-1 WHERE isbn=?";
jdbcTemplate.update(sql, isbn);
}
}
事务细节
1.@Transactional中的属性
>isolation-Isolation:事务的隔离级别
>propagation-Propagation:事务的传播行为
>noRollbackFor-Class[]:哪些异常事务可以不回滚(可以让默认回滚的异常不回滚)
>noRollbackForClassName-String[]:
>roobackFor-Class[]:让原本不回滚的异常 指定让其回滚
>rollbackForClassName-String[]:
>readOnly-boolean:设置事务为只读事务:可以进行事务优化,加快查询速度,不需要管事务中的增删改等操作
>timeout-int:超时:事务超过指定执行时长后自动终止并回滚
异常分为运行时异常和编译时异常,运行时异常:可以不用处理,默认为回滚。 编译时异常:需要try-catch,或者throws,默认不回滚。
隔离级别:数据库系统必须具有隔离并发运行各个事务的能力,使它们不会互相影响(以前因为并发问题会出现脏读、不可重复读、幻读的情况:脏读就是 修改数据但没有提交时被别人读出,最后事务发生回滚。不可重复读就是 两次读的值不一样。 幻读就是 每次读出的数据条数不同)
2.有事务的业务逻辑,容器中保存的是这个业务逻辑的代理对象
3.传播行为:当事务中嵌套事务时,当被嵌套的事务发生回滚时,可以设置嵌套在外面的事务是否发生回滚。
当子事务设置为REQUIRED时,该子事务会服从外层事务,所有属性都继承外层事务的属性。(例如,子事务设置timeout时是失效的)
4.XML配置事务
<!-- 配置事务切面 -->
<aop:config>
<aop:pointcut
expression="execution(* com.atguigu.tx.component.service.BookShopServiceImpl.purchase(..))"
id="txPointCut"/>
<!-- 将切入点表达式和事务属性配置关联到一起 -->
<aop:advisor advice-ref="myTx" pointcut-ref="txPointCut"/>
</aop:config>
<!-- 配置基于XML的声明式事务 -->
<tx:advice id="myTx" transaction-manager="transactionManager">
<tx:attributes>
<!-- 设置具体方法的事务属性 -->
<tx:method name="find*" read-only="true"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="purchase"
isolation="READ_COMMITTED"
no-rollback-for="java.lang.ArithmeticException,java.lang.NullPointerException"
propagation="REQUIRES_NEW"
read-only="false"
timeout="10"/>
</tx:attributes>
</tx:advice>