spring的事务管理,分为编程式事务和声明式事务
1.编程式事务,通过手动的方式进行控制事务。
(1)利用 原生的 PlatformTransactionManager的方法
TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
void commit(TransactionStatus var1) throws TransactionException;
void rollback(TransactionStatus var1) throws TransactionException;
(2)利用TransactionTemplate 简化。
2.声明式事务,代码侵入性小。
(1)基于TransactionProxyFactoryBean的方式(很少使用)
需要为每个事务管理的类配置一个TransactionProxyFactoryBean进行管理。使用时还需要在类中注入该代理类。
(2)基于AspectJ的方式(常使用)
配置好之后,按照方法的名字进行管理,无需再类中添加任何东西。
(3)基于注解的方式(经常使用)
配置简单,在业务层类上添加注解@Transactional。
一、编程式事务
1. 通过 transactionManager事务管理器
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
DataSourceTransactionManager transactionManager;
@Autowired
TransactionTemplate transactionTemplate;
public void doSubmit(){
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setIsolationLevel(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus transactionStatus = transactionManager.getTransaction(def);
try{
//操作数据库操作.......
transactionManager.commit(transactionStatus);
}catch (Exception e){
transactionManager.rollback(transactionStatus);
}
}
- DefaultTransactionDefinition:事务定义,定义如隔离级别、传播行为等,即在本示例中隔离级别为ISOLATION_READ_COMMITTED(提交读),传播行为为PROPAGATION_REQUIRED(必须有事务支持,即如果当前没有事务,就新建一个事务,如果已经存在一个事务中,就加入到这个事务中)。
- TransactionStatus:事务状态类,通过PlatformTransactionManager的getTransaction方法根据事务定义获取;获取事务状态后,Spring根据传播行为来决定如何开启事务;
- JdbcTemplate:通过JdbcTemplate对象执行相应的SQL操作,且自动享受到事务支持,注意事务是线程绑定的,因此事务管理器可以运行在多线程环境;
- transactionManager.commit(transactionStatus):提交status对象绑定的事务;
- transactionManager.rollback(transactionStatus):当遇到异常时回滚status对象绑定的事务。
当然这个我们也可以包装一下,将一些方法封装一下
package com.tzw.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
@Service
public class TransactionUtil {
@Autowired
DataSourceTransactionManager transactionManager;
TransactionStatus transactionStatus;
/**
* 开启事务
*/
public void open(){
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
transactionStatus = transactionManager.getTransaction(def);
}
/**
* 提交事务
*/
public void commit(){
transactionManager.commit(transactionStatus);
}
/**
* 回滚事务
*/
public void rollBack(){
transactionManager.rollback(transactionStatus);
}
}
使用时。直接调用 open commit rollBack方法。
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
DataSourceTransactionManager transactionManager;
@Autowired
TransactionTemplate transactionTemplate;
@Autowired
TransactionUtil transactionUtil;
public void doSubmit(){
transactionUtil.open();
try{
//操作数据库操作.......
transactionUtil.commit();
}catch (Exception e){
transactionUtil.rollBack();
}
}
2.通过TransactionTemplate 简化事务管理器。
其实我觉得并没有有简化多少。哈哈
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
DataSourceTransactionManager transactionManager;
@Autowired
TransactionTemplate transactionTemplate;
@Autowired
TransactionUtil transactionUtil;
public void doSubmit_01(){
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try{
//数据库数据操作.......
}catch (Exception e){
transactionStatus.setRollbackOnly();
}
}
});
}
二、声明式事务
1.基于TransactionProxyFactoryBean的方式
<!--方式1: 基于TransactionProxyFactoryBean实现,底层是通过AOP的方式实现的-->
<bean id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!--注入事务管理器-->
<property name="transactionManager" ref="transactionManager"></property>
<!--配置目标对象-->
<property name="target" ref="coreService"></property>
<!--注入事务的属性-->
<property name="transactionAttributes">
<props>
<prop key="submit*">PROPAGATION_REQUIRED,+java.lang.ArithmeticException</prop>
<!-- 格式:
<prop key="方法">参数</prop>
* PROPAGATION :事务的传播行为
* ISOLATION :事务的隔离级别
* readOnly :只读.(不可以进行修改、插入、删除)
* -Exception :发生哪些异常回滚事务
* +Exception :发生哪些异常事务不回滚
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
-->
<!--<prop key="transfer">PROPAGATION_REQUIRED</prop> -->
</props>
</property>
</bean>
2.基于aspect
<!--方式2: 通过aspectj配置事务管理器-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="updateClient11111" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.tzw.service.TzwService.*(..))"></aop:pointcut>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />
</aop:config>
3.利用注解
<!--方式3: 开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"/>
事务处理java 类
package com.tzw.service;
import com.tzw.entity.EcifClient;
import com.tzw.mapper.EcifClientMapper;
import com.tzw.util.TransactionUtil;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Map;
@Service
public class TzwService {
@Autowired
TransactionUtil transactionUtil;
@Autowired
EcifClientMapper ecifClientMapper;
public void getClient(){
List<Map<String, Object>> maps = ecifClientMapper.selectAllList();
System.out.println(maps.toString());
}
public void updateClient_01(){
transactionUtil.open();
try{
System.out.println("开始执行新增----");
EcifClient ecifClient = new EcifClient();
ecifClient.setClientId("0000000008");
ecifClient.setClientName("王五");
ecifClient.setClientNameEn("wu");
int insert = ecifClientMapper.insert(ecifClient);
System.out.println("执行完成了新增----");
EcifClient ecifClient1 = new EcifClient();
ecifClient1.setClientId("0000000001");
ecifClient1.setClientName("张三------------123133333333333333333333333333333333321323233333333333333333333333333");
ecifClient1.setClientNameEn("zs============");
int i = ecifClientMapper.updateByPrimaryKey(ecifClient1);
transactionUtil.commit();
}catch (Exception e){
System.out.println("抛出异常");
transactionUtil.rollBack();
}
}
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void updateClient(){
System.out.println("开始执行新增----");
EcifClient ecifClient = new EcifClient();
ecifClient.setClientId("0000000008");
ecifClient.setClientName("王五");
ecifClient.setClientNameEn("wu");
int insert = ecifClientMapper.insert(ecifClient);
System.out.println("执行完成了新增----");
EcifClient ecifClient1 = new EcifClient();
ecifClient1.setClientId("0000000001");
ecifClient1.setClientName("张三------------123133333333333333333333333333333333321323233333333333333333333333333");
ecifClient1.setClientNameEn("zs============");
int i = ecifClientMapper.updateByPrimaryKey(ecifClient1);
transactionUtil.commit();
}
}
这里展示了编程事务控制,和注解式控制。其实Aspectj只需要把这个方法名配置就好了。
基于TransactionProxyFactoryBean 的目前没有展示,后期会补上,他也不常用。
完整xml文件
<?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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
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.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.tzw"></context:component-scan>
<!--数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"></property>
<property name="username" value="tzw"></property>
<property name="password" value="tzw"></property>
</bean>
<!--原生jdbc模板-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--事务管理器-->
<bean id="transactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--事务管理模板,一般用于简化编程式事务-->
<bean id="transactionTemplate" class ="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
<!--方式1: 基于TransactionProxyFactoryBean实现,底层是通过AOP的方式实现的-->
<bean id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!--注入事务管理器-->
<property name="transactionManager" ref="transactionManager"></property>
<!--配置目标对象-->
<property name="target" ref="coreService"></property>
<!--注入事务的属性-->
<property name="transactionAttributes">
<props>
<prop key="submit*">PROPAGATION_REQUIRED,+java.lang.ArithmeticException</prop>
<!-- 格式:
<prop key="方法">参数</prop>
* PROPAGATION :事务的传播行为
* ISOLATION :事务的隔离级别
* readOnly :只读.(不可以进行修改、插入、删除)
* -Exception :发生哪些异常回滚事务
* +Exception :发生哪些异常事务不回滚
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
-->
<!--<prop key="transfer">PROPAGATION_REQUIRED</prop> -->
</props>
</property>
</bean>
<!--方式2: 通过aspectj配置事务管理器-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="updateClient11111" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.tzw.service.TzwService.*(..))"></aop:pointcut>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />
</aop:config>
<!--方式3: 开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!--以上是spring的事务管理器,与下面的 数据库框架没有任何关系-->
<!--以下是 mybatis 框架的配置,一共有两步,1,sqlSessionFactory 2. 自动扫描对象映射关系 org.mybatis 和 tk.mybatis-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:mybatis.xml"></property>
<property name="mapperLocations">
<array>
<value>classpath*:mapper/clientMapper.xml</value>
</array>
</property>
</bean>
<!--自动扫描对象关系映射 -->
<!--<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!–指定会话工厂,如果当前上下文中只定义了一个则该属性可省去 –>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
<!– 指定要自动扫描接口的基础包,实现接口 –>
<property name="basePackage" value="com.tzw.mapper"></property>
</bean>-->
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定会话工厂,如果当前上下文中只定义了一个则该属性可省去 -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
<!-- 指定要自动扫描接口的基础包,实现接口 -->
<property name="basePackage" value="com.tzw.mapper"></property>
<property name="properties">
<value>mappers=tk.mybatis.mapper.common.Mapper</value>
</property>
</bean>
</beans>