Spring声明式事务配置使用详解

yizhihongxing

Spring声明式事务配置使用详解

什么是事务

事务是一组完整的业务操作,这些操作作为一个原子单元,要么全部成功,要么全部失败回滚,保证数据库中的数据一致性。

声明式事务的优点

Spring框架提供的声明式事务管理有以下几个好处:

  1. 代码简洁:通过使用声明式事务管理,Spring框架可以将所有的数据库事务处理的代码都放在配置文件中,这样就不需要在业务逻辑代码中手动控制事务的开启、提交或回滚事务的操作。

  2. 不受编程语言的限制:不管是Java还是其他任何支持AOP的编程语言,都可以使用Spring框架提供的声明式事务管理服务。这就意味着,只要是符合AOP的编程语言,都可以使用Spring框架提供的事务管理服务。

  3. 无代码侵入:使用声明式事务管理的好处之一是它不会对业务逻辑产生任何影响,因此,业务逻辑代码与事务管理的代码可以很好地分离。在这种情况下,业务逻辑代码可以集中在处理业务逻辑方面,而事务管理的代码可以集中在单独的配置文件中。

Spring声明式事务配置

Spring提供了两种方式实现声明式事务:

  1. 基于XML的声明式事务:该方式使用XML配置文件来配置声明式事务。

  2. 基于注解的声明式事务:该方式使用注解来配置声明式事务。

本文将介绍基于XML的声明式事务配置。

配置Spring声明式事务

配置事务管理器

在使用Spring声明式事务之前,必须先配置事务管理器,配置方式如下:

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

其中,transactionManager是事务管理器的id,class指定了使用的事务管理器类,这里使用的是DataSourceTransactionManager类,这是一个基于DataSource的事务管理器,property设置了dataSource属性,这里的dataSource是数据源的id,我们需要在该配置文件中提前定义。

配置数据源

在配置事务管理器时,需要指定使用的数据源,因此,需要在配置文件中提前配置数据源。数据源的配置方式因你所使用的具体数据源而异。在这里,我们演示使用Apache的Commons DBCP数据源的配置方式。以下是数据源配置的一些示例代码:

<!--数据库驱动-->
<bean id="driverManagerDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/mydatabase?serverTimezone=UTC&amp;useSSL=false" />
    <property name="username" value="myusername" />
    <property name="password" value="mypassword" />
    <property name="initialSize" value="5" /> <!--初始化连接数-->
    <property name="maxIdle" value="10" /> <!--最大空闲连接-->
    <property name="maxTotal" value="100" /> <!--最大连接数量-->
    <property name="removeAbandonedOnBorrow" value="true" /> <!--连接过期是否自动回收-->
</bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
    <property name="targetDataSource" ref="driverManagerDataSource"/>
</bean>

在上面的代码中,我们首先定义了一个Commons DBCP数据源,并指定了驱动类、URL、用户名和密码等参数。该数据源配置完成后,使用org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy类包装数据源,将数据源设置为"targetDataSource"属性。

配置DAO

DAO层是访问数据库的一个封装层,需要在DAO中调用通过事务提交的代码。因此,在DAO中,必须使用Spring提供的JdbcTemplate类来使用Spring声明式事务。以下是一个DAO示例:

public class UserDAO {
    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    //添加用户
    public int addUser(User user) {
        String sql = "INSERT INTO user(username,password,age) VALUES (?,?,?)";
        return this.jdbcTemplate.update(sql, new Object[] { user.getUsername(), user.getPassword(), user.getAge() });
    }
}

在上面的代码中,我们在UserDAO类中使用Spring提供的JdbcTemplate类与数据源进行交互,并使用其中提供的update方法提交SQL语句。

配置Spring声明式事务

现在,我们已经配置好了事务管理器、数据源和DAO。下面,我们来配置Spring声明式事务。事务配置方式如下:

<!--声明式事务配置-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="add*" propagation="REQUIRED" />
        <tx:method name="update*" propagation="REQUIRED" />
        <tx:method name="delete*" propagation="REQUIRED" />
        <tx:method name="*" propagation="REQUIRED" read-only="true" />
    </tx:attributes>
</tx:advice>

<!--事务设置-->
<aop:config>
    <aop:pointcut id="allMethod" expression="execution(* com.example.*.*DAO.*(..))" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="allMethod" />
</aop:config>

其中,aop:config标签用来定义切入点和通知类型,这里的pointcut表示对所有DAO类中的全部方法进行拦截,通知类型为传播方式为REQUIRED的声明式事务管理。在这里,我们定义了四种类型的拦截方式:

  1. 对add、update、delete*三类方法进行事务管理,传播方式为REQUIRED。

  2. 对所有方法进行事务管理,传播方式为REQUIRED,同时设置readOnly为true,表示只读性质事务。

声明式事务使用示例

在上面的配置完成后,我们可以进行事务间的开启、提交和回滚操作,以下是几个使用示例。

1. 添加用户(事务成功)

//创建用户DAO
UserDAO userDAO = new UserDAO();
userDAO.setDataSource(dataSource);

//新建事务
DefaultTransactionDefinition transDefinition = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(transDefinition);
try {
    //业务操作
    User newUser = new User();
    newUser.setUsername("testuser");
    newUser.setPassword("testpassword");
    newUser.setAge(18);

    int result = userDAO.addUser(newUser);

    System.out.println("添加用户:" + result);

    //提交事务
    transactionManager.commit(status);
} catch (Exception e) {
    //回滚事务
    transactionManager.rollback(status);
    e.printStackTrace();
}

在上面的示例中,我们使用transactionManager开启一个事务,并定义一个TransactionStatus对象status,用于管理事务的状态。此后,我们使用DAO类添加一个新用户,当添加完成后,使用事务管理器对该事务进行提交。

2. 添加用户(事务失败)

//创建用户DAO
UserDAO userDAO = new UserDAO();
userDAO.setDataSource(dataSource);

//新建事务
DefaultTransactionDefinition transDefinition = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(transDefinition);
try {
    //业务操作
    User newUser = new User();
    newUser.setUsername("testuser");
    newUser.setPassword("testpassword");
        newUser.setAge(200); //年龄不合法,导致事务失败

    int result = userDAO.addUser(newUser);

    System.out.println("添加用户:" + result);

    //提交事务
    transactionManager.commit(status);
} catch (Exception e) {
    //回滚事务
    transactionManager.rollback(status);
    e.printStackTrace();
}

在上面的示例中,我们使用transactionManager开启一个事务,并定义一个TransactionStatus对象status,用于管理事务的状态。此后,我们使用DAO类添加一个新用户,当添加完成后,使用事务管理器对该事务进行提交。由于该用户年龄属性不合法,此时事务将失败,会回滚数据。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring声明式事务配置使用详解 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Lombok在idea中的使用教程

    这里我将详细讲解 Lombok 在idea中的使用教程。 Lombok是什么 Lombok 是一个简化 Java 代码的工具,通过使用注解来消除一些必须有但显得很臃肿的 Java 代码。 安装Lombok 首先,我们需要在项目的 maven 配置文件中,添加如下依赖: <dependency> <groupId>org.project…

    Java 2023年5月26日
    00
  • Java String字符串和Unicode字符相互转换代码

    下面是Java String字符串和Unicode字符相互转换代码的完整攻略: Unicode字符和Java String字符串的相互转换 在Java编程中,我们有时需要将Unicode字符和Java String字符串相互转换。Unicode字符是一个标准,它规定了所有字符及其对应的码点。而Java String字符串是由Unicode字符序列组成的。 U…

    Java 2023年5月20日
    00
  • Java实现图书借阅系统

    Java实现图书借阅系统的完整攻略 介绍 本文将介绍如何使用Java编程语言实现简单的图书借阅系统。该系统包括了书籍的添加、删除和查询功能,以及具有借阅和归还功能的用户界面。 开发环境 本文将使用Java编程语言进行开发。Java具有强大的面向对象编程特性,并且易于学习和使用。我们将使用Java的标准库和一些第三方库来实现该系统。 具体的开发环境和所使用的库…

    Java 2023年5月19日
    00
  • 详解Java中的日期类

    详解Java中的日期类 Java提供了许多用于处理日期和时间的内置类,其中包括日期类、时间类、日历类等。在这些类中,最基础和常用的是日期类java.util.Date和日期格式化类java.text.SimpleDateFormat。 java.util.Date类 java.util.Date类表示了一个时间点,它存储了一个long类型的整数值,该值代表了…

    Java 2023年5月20日
    00
  • Spring Security+JWT实现认证与授权的实现

    下面我就来详细讲解一下“Spring Security+JWT实现认证与授权的实现”的完整攻略。 一、准备工作 在开始讲解实现的过程之前,我们需要先进行一些准备工作: 在项目的pom.xml文件中引入相应的依赖: <dependency> <groupId>org.springframework.boot</groupId&gt…

    Java 2023年5月20日
    00
  • 浅析Java中Data类的应用

    浅析Java中Data类的应用 什么是Data类 Data类是Java中常用的日期操作类,用于处理日期和时间,并提供了对日期和时间的格式化,解析,计算以及转换等操作。 Data类位于java.util包中,可以通过import java.util.Data;来引入。 Data类的基本用法 创建Data对象 在Java中,我们可以通过多种方式创建Data对象。…

    Java 2023年5月20日
    00
  • 深入解析Java的Spring框架中的混合事务与bean的区分

    深入解析Java的Spring框架中的混合事务与bean的区分,这是一个比较广泛的话题,我们可以从以下几个方面进行讲解: Spring框架事务管理的概述 Spring混合事务的定义与原理 Spring Bean的定义与作用 如何区分Spring混合事务与Bean 1. Spring框架事务管理的概述 Spring框架中的事务管理是一种重要的机制,可以帮助我们…

    Java 2023年5月20日
    00
  • 一文带你学习Java中的线程

    一文带你学习Java中的线程 什么是线程 线程是操作系统能够进行运算调度的最小单位。也就是说,线程是进程中的一个实体,是被系统独立调度和分配CPU时间的基本单位,是比进程更小的能独立运行的基本单位。 在Java中,线程是一个单独的执行路径,每个线程都有自己的栈和程序计数器。JVM运行线程调度,每个线程的执行顺序和时间是由操作系统决定。 如何创建线程 在Jav…

    Java 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部