Spring基础使用八

基于注解的声明式事务

Spring提供了@Transactional注解实现事务管理

配置@Transactional

  1. 配置Spring的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: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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

<!--扫描组件-->
<context:component-scan base-package="com.wfy"></context:component-scan>
<!-- 导入jdbc.properties-->
    <context:property-placeholder location="jdbc.properties"></context:property-placeholder>
<!-- 创建数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
    <bean 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>
        <!--
        开启事务驱动注解
        将使用@Translational注解所标识的方法或类中所有的方法使用事务进行管理
        transaction-manager属性设置事务管理器的id
        若事务管理器的bean的id默认为transactionManager,则该属性可以默认不写
        -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

事务管理:

通过tx:annotational-driven元素配置事务注解驱动,tx:annotational-driven元素中有一个常用属性transactional-manager,该属性用于指定事务管理器

<!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
        <!--
        开启事务驱动注解
        将使用@Translational注解所标识的方法或类中所有的方法使用事务进行管理
        transaction-manager属性设置事务管理器的id
        若事务管理器的bean的id默认为transactionManager,则该属性可以默认不写
        -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
  1. 在service层使用@Transactional注解
package com.wfy.service.impl;

import com.wfy.dao.BookDao;
import com.wfy.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private BookDao bookDao;
    @Override
    @Transactional
    public void buyBook(Integer userId, Integer bookId) {
        //查询图书的价格
      Integer price=  bookDao.getPriceById(bookId);
        //更新图书的库存
        bookDao.updateBook(bookId);
        //更新用户的余额
        bookDao.updateBalance(userId,price);
    }
}
  1. 测试案例
package com.wfy.spring.test;

import com.wfy.controller.BookController;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:tx-annotation.xml")
public class TxByAnnotation {

    /**声明式事务的配置步骤:
     * 1.在Spring的配置文件中配置事务管理器
     * 2.开启事务的注解驱动
     *在需要被事务管理的方法上,添加@Transactional注解,该方法就会被事务管理
     * @Transactional注解标识的位置:
     * 1.标识在方法上
     * 2.标识在类上,则类中所有的方法都会被事务管理
     */
    @Autowired
    private BookController bookController;
    @Test
    public void testByBook(){
        bookController.buyBook(1,1);
    }
}

只有当声明的事务中的所有方法全部执行,数据才会更新

声明式事务的属性

  • 只读
 @Transactional(readOnly = true)

如果对增删改操作设置只读,则会报以下错误:

Caused by: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed

  • 超时
  @Transactional(timeout = 3    )

超时则会报以下错误:

org.springframework.transaction.TransactionTimedOutException: Transaction timed out: deadline was Tue Nov 01 19:20:14 CST 2022

事务在执行过程中,有可能因为遇到某些问题,导致程序卡住,从而长时间占用数据库资源。此时程序很可能会出现问题,出现问题的程序应该会被回滚,撤销它已做的操作,事务结束,把资源让出来,让其他正常程序可以执行。

超时回滚,释放资源

  • 回滚策略

声明式事务默认只针对运行时异常回滚,编译时异常不回滚。

    @Transactional(noRollbackFor =ArithmeticException.class    )

用于指定不会导致事务回滚的异常类数组

  @Transactional(noRollbackForClassName = "java.lang.ArithmeticException")

用于指定不会导致事务回滚的异常类数组名称

  @Transactional(RollbackFor)

用于指定导致事务回滚的异常类数组

  @Transactional(RollbackForClassName)

用于指定导致事务回滚的异常类数组名称

  • 事务隔离级别

数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别。SQL标准中规定了各种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。

  @Transactional( isolation = Isolation.DEFAULT)

用于指定事务的隔离级别

  • 传播行为
 @Transactional(propagation = Propagation.REQUIRED)

默认情况,表示如果当前线程上有已经开启的事务可用,那么就在这个事务中运行。

  @Transactional( propagation = Propagation.REQUIRES_NEW)

表示不管当前线程上是否有已经开启的事务,都要开启新事务。

基于XML的声明式事务

配置Spring的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: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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--扫描组件-->
    <context:component-scan base-package="com.wfy"></context:component-scan>
    <!-- 导入jdbc.properties-->
    <context:property-placeholder location="jdbc.properties"></context:property-placeholder>
    <!-- 创建数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
    <bean 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>
<!-- 配置事务通知-->
      <tx:advice id="tx" transaction-manager="transactionManager">
          <tx:attributes>
              <tx:method name="buyBook"/>
          </tx:attributes>
      </tx:advice>

    <aop:config>
        <aop:advisor advice-ref="tx" pointcut="execution(* com.wfy.service.impl.*.*(..))"></aop:advisor>
    </aop:config>
</beans>

配置文件:

    <!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
<!-- 配置事务通知-->
      <tx:advice id="tx" transaction-manager="transactionManager">
          <tx:attributes>
              <tx:method name="buyBook"/>
          </tx:attributes>
      </tx:advice>

    <aop:config>
        <aop:advisor advice-ref="tx" pointcut="execution(* com.wfy.service.impl.*.*(..))"></aop:advisor>
    </aop:config>

注意:基于xml实现的声明式事务,必须引入aspectJ的依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.3.23</version>
</dependency>

原文地址:http://www.cnblogs.com/wfy-studying/p/16849067.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性