Spring声明式事务管理

本文深入讲解了声明式事务和编程式事务的区别,包括基于TransactionProxyFactoryBean、AspectJ及@Transactional注解的配置方法,详细解释了事务隔离级别和传播行为,帮助读者全面理解并掌握事务管理的核心概念。

声明式事务和编程式事务

编程式事务使用TransactionTemplate ,是硬编码

*声明式事务是基于AOP。对指定方法前后进行拦截,在目标方法开始之前创建或加入一个事务,在执行完目标方法之后根据执行结果提交或者回滚事务。

1 基于TransactionProxyFactoryBean

xml配置文件

   <!--导入外部文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--连接池配置-->
    <bean id="dataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driverClass}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
    <!--业务层类-->
    <bean id="accountService" class="com.spring.transaction.demo2.AccountServiceImpl">
         <property name="accountDao" ref="accountDao"/>
    </bean>
    <bean id="accountDao" class="com.spring.transaction.demo2.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--配置事务管理器-->
    <bean id="transactionManager" 
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--配置业务层代理-->
    <bean id="accountServiceProxy" 
    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <!--配置目标对象-->
        <property name="target" ref="accountService"/>
        <!--注入事务管理器-->
        <property name="transactionManager" ref="transactionManager"/>
        <!--注入事务属性-->
        <property name="transactionAttributes">
            <props>
                <!--prop格式
                    * PROPAGATION   传播行为
                    * ISOLATION     事务隔离级别
                    * readOnly      只读
                    * -Exception    发生那些异常回滚
                    * +Exception    发生那些异常不回滚
                -->
                <prop key="transfer">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
<!--声明式事务管理  基于TransactionProxyFactoryBean-->

      注:在注入Service时需要注入代理类

 //注入代理类
    //@Resource(name = "accountService")
    @Resource(name = "accountServiceProxy")
    private AccountService accountService;

2基于AspectJ

  <!--导入外部文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--连接池配置-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driverClass}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
    <!--业务层类-->
    <bean id="accountService" class="com.spring.transaction.demo4.AccountServiceImpl">
         <property name="accountDao" ref="accountDao"/>
    </bean>
    <!--配置DAo-->
    <bean id="accountDao" class="com.spring.transaction.demo4.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--配置事务管理器-->
    <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="transfer"/>-->
       <!--</tx:attributes>-->

        <tx:attributes>
          <tx:method name="*" />
        </tx:attributes>
    </tx:advice>
    <!--配置切面-->
    <aop:config>
        <!--配置切入点     匹配demo3包下Service类-->
        <aop:pointcut id="pointcut1" expression="execution(* 
         com.spring.transaction.demo3.*Service*.*(..))"/>
        <!--配置切面-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
    </aop:config>

3基于@Transactional注解

配置好后只需要在指定的类或者方法上贴@Transactional注解(对public以外的方法是不会起作用的),在用Aop切入方法时,方法的类型要设置成public共有类型才会有效!

    <!--导入外部文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--连接池配置-->
    <bean id="dataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driverClass}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!--业务层类-->
    <bean id="accountService" class="com.spring.transaction.demo4.AccountServiceImpl">
         <property name="accountDao" ref="accountDao"/>
    </bean>

    <!--配置Dao-->
    <bean id="accountDao" class="com.spring.transaction.demo4.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置事务管理器-->
    <bean id="transactionManager" 
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--开启注解事务-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

事务隔离级别

为了解决并发时产生的 脏读,不可重复读,幻读 产生的。

脏读事务A读到了事务B还没有提交的数据(事务B修改了数据,此时A读了该数据,B因发生异常回滚,A就读到了脏数据)

不可重复读:在一个事务里面读取了两次某个数据,读出来的数据不一致(A开启事务第一次读到数据后,事务B修改并提交了数据,此时切换回事务A又一次读取该数据,两次数据读取不一致,这就形成了不可重复读)

幻读:在一个事务中两次查询返回的记录数不一致(A事务第一次查询了N条记录,此时B事务又添加了新的记录或删除记录,当事务A再次读取时发现和之前读取的记录数不一致)   

隔离级别由低到高(Spring 通过 ISOLATION 属性配置

1  DEFAULT  数据库默认级别           mysql 默认 REPEATABLE_READ        oracle默认 READ_COMMITED

2  READ_UNCOMMITTED              可以读取未提交的数据   会导致 脏读,不可重复读,幻读

3  READ_COMMITED                      可以读取已提交的数据   可以解决脏读

4  REPEATABLE_READ                 第一次读取时对该数据加锁在当前事务结束前防止其他事物修改,可解决脏读,不可重复读

5  SERLALIZABLE                           不管多少事物,只能挨个完成(很少使用)

 事务传播行为

 通过PROPAGATION属性配置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值