spring 的事务管理

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">
        &lt;!&ndash;指定会话工厂,如果当前上下文中只定义了一个则该属性可省去 &ndash;&gt;
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
        &lt;!&ndash; 指定要自动扫描接口的基础包,实现接口 &ndash;&gt;
        <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>

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值