Spring事务管理
概念:事务一般特指数据库事务,是指作为一个程序执行单元执行的一系列操作,要么完全执行,要么完全不执行
在业务层封装事务
什么是事务
- 原子性(atomicity):一个事务是一个不可分割的工作单位
- 一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态
- 隔离性(isolation):一个事务的执行不能被其他事物干扰
- 持久性(durability):一个事务一旦提交,他对数据库中数据的改变应该是永久性的
MySQL事务处理
- 基本规则
- MySQL中只有使用了Innodb数据库引擎的数据库或表才支持事务。
- MySQL默认以自动提交(autocommit)模式运行。
语句: - BEGIN(STARTTRANSACTION) 显式地开启一个事务
- COMMIT 提交事务,并使用对数据库进行的所有修改变为永久性的
- ROLLBACK 回滚事务,并撤销正在进行的所有未提交的修改
事务并发问题
- 脏读
解决:只能读取永久性数据,不能读取内存中的数据 - 不可重复读
解决:锁行 - 幻读
解决:锁表事务隔离级别
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交( read-uncommitted ) | 是 | 是 | 是 |
读已提交( read-committed ) | 否 | 是 | 是 |
可重复读( repeatable-read ) | 否 | 否 | 是 |
串行化( serializable ) | 否 | 否 | 否 |
-
语句
--- select@@tx_isolation- 查询默认隔离级别
--- set session transaction isolation level XXX - 设置当前会话隔离级别
JDBC事务处理
- 查询默认隔离级别
-
Connection接口
-
JDBC的事务处理是基于Connection的,JDBC通过COnnection对象进行事务管理
-
JDBC默认事务处理行为是自动提交
-
事务相关方法
-
setAutoCommit
-
设置自动提交
-
commit
-
事务提交
-
rollback
-
回滚事务
JDBC事务隔离级别
-
TRANSACTION_NONE(不支持事务) 0;
-
TRANSACTION_READ_UNCOMMITTED(读未提交)1;
-
TRANSACTION_READ_COMMITTED(读已提交)2;
-
TRANSACTION_REPEATABLE_READ(可重复读)4;
-
TRANSACTION_SERIALIZABLE (串行化)8;
-
事务隔离级别设置
-
getTransactionIsolation 获取当前隔离级别(只能获取到上面的0 1 2 4 8 )
-
setTransactionIsolation 设置隔离级别 默认为4(同上)
Spring事务处理API
TransationDefinition接口
-
隔离级别
-
ISOLATION_DEFAULT(使用数据库默认)
-
ISOLATION_READ_UNCOMMITTED
-
ISOLATION_READ_COMMITTED
-
ISOLATION_REPEATABLE_READ
-
ISOLATION_SERIALIZABLE
-
默认超时
-
TIMEOUT_DEFAULT : 30秒
事务传播行为
-
PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。(Spring默认)
-
PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
-
PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
-
PROPAGATION_REQUIRES NEW:新建事务,如果当前存在事务,把当前事务挂起。
-
PROPAGATIONNOT SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
-
PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
-
PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,就新建一个事务。
Spring编程式事务处理
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://47.114.2.235:3306/Spring?useUnicode=true&characterEncoding=utf-8"/> <property name="username" value="Spring"/> <property name="password" value="Spring"/> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource" /> </bean> <context:component-scan base-package="dao"/>
-
基于底层API的编程式事务管理
-
PlatformTransactionManager 事务管理器
-
TransactionDefinition 事务的一些基础信息,如超时时间、隔离级别、传播属性等
-
TransactionStatus 事务的一些状态信息,如是否一个新的事务、是否已被标记为回滚
-
基于TransactionTemplate的编程式事务管理
//OrderServiceImpl
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private TransactionDefinition transactionDefinition;
public void addOrder(Order order) {
order.setCreateTime(new Date());
order.setStatus("代付款");
TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
try {
orderDao.insert(order);
Product product = productDao.select(order.getProductsId());
product.setStock(product.getStock() - order.getNumber());
productDao.update(product);
transactionManager.commit(transactionStatus);
} catch (Exception e) {
transactionManager.rollback(transactionStatus);
}
}
}
//XML
<import resource="spring-dao.xml"/>
<context:component-scan base-package="service.impl2"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionDefinition" class="org.springframework.transaction.support.DefaultTransactionDefinition">
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
</bean>
- TransactionTemplate(为简化步骤而存在)
//OrderServiceImpl
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
@Autowired
private TransactionTemplate transactionTemplate;
public void addOrder(Order order) {
order.setCreateTime(new Date());
order.setStatus("代付款");
transactionTemplate.execute(new TransactionCallback() {
@Override
public Object doInTransaction(TransactionStatus transactionStatus) {
try {
orderDao.insert(order);
Product product = productDao.select(order.getProductsId());
product.setStock(product.getStock() - order.getNumber());
productDao.update(product);
} catch (Exception e) {
transactionStatus.setRollbackOnly();
}
return null;
}
});
}
}
//XML
<import resource="spring-dao.xml"/>
<context:component-scan base-package="service.impl1"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
Spring声明式事务处理
- 概述
一Spring 的声明式事务处理是建立在AOP的基础之上的。其本质是对方法前
后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
一建议在开发中使用声明式事务 ,是因为这样可以使得业务代码纯粹干净,方便后期的代码维护。
//OrderServiceImpl
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
public void addOrder(Order order) {
order.setCreateTime(new Date());
order.setStatus("代付款");
orderDao.insert(order);
Product product = productDao.select(order.getProductsId());
product.setStock(product.getStock() - order.getNumber());
productDao.update(product);
}
}
基于TransactionInterceptor的声明式事务处理
<import resource="spring-dao.xml"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="orderServiceTarget" class="service.impl.OrderServiceImpl"/>
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="search*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="orderService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="orderServiceTarget"/>
<property name="interceptorNames">
<list>
<idref bean="transactionInterceptor"/>
</list>
</property>
</bean>
基于TransactionProxyFactoryBean的声明式事务处理(简化上一方法的配置)
//XML
<import resource="spring-dao.xml"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="orderServiceTarget" class="service.impl.OrderServiceImpl"/>
<bean id="orderService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="search*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
<property name="target" ref="orderServiceTarget"/>
</bean>
基于命名空间的声明式事务管理(频繁 更合理)
<import resource="spring-dao.xml"/>
<context:component-scan base-package="service.impl"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" propagation="REQUIRED" read-only="true"/>
<tx:method name="find*" propagation="REQUIRED" read-only="true"/>
<tx:method name="search*" propagation="REQUIRED" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<!-- 定义切面 execution(* service.impl.*.*(..)):任意返回值 impl包下所有的所有类所有方法的任意返回值还有任意参数-->
<aop:pointcut id="pointcut" expression="execution(* service.impl.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
基于@Transactional的声明式事务管理(频繁 更流行)
//XML
<import resource="spring-dao.xml"/>
<context:component-scan base-package="service.impl3"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 使用tx驱动指定关于事务的注解,并且指定事务管理器-->
<tx:annotation-driven transaction-manager="transactionManager"/>
//OrderServiceImpl
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
// @Transactional 使用默认
@Transactional(propagation = Propagation.REQUIRED)
public void addOrder(Order order) {
order.setCreateTime(new Date());
order.setStatus("代付款");
orderDao.insert(order);
Product product = productDao.select(order.getProductsId());
product.setStock(product.getStock() - order.getNumber());
productDao.update(product);
}
}
总结
- 事务概念
- 完成某个业务功能所需的一系列操作。
- 特性:原子性( atomicity)、 -致性( consistency )、隔离性( isolation)、 持久性( durability )
- 并发问题:脏读、不可重复读、幻读
- 事务隔离级别:读未提交( read-uncommitted )、读已提交( read- committed)、可重复读( repeatable-read)、 串行化( serializable )
- Spring事务处理
- API
- 声明式事务处理
共有 0 条评论