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

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日

相关文章

  • jquery动态改变form属性提交表单

    如果你想通过jQuery来动态地改变表单(form)的属性和值,这里提供一些可以参考的方法和示例。 改变表单属性 可以使用attr()函数来改变表单属性。 $("form").attr("action", "new_action_url"); 这个方法将表单的action属性更改为new_actio…

    Java 2023年6月15日
    00
  • Java GC垃圾回收算法分析

    Java GC垃圾回收算法分析 什么是Java垃圾回收 Java垃圾回收是指在Java虚拟机运行时,对无用对象所占用的内存进行回收,以便为新的对象腾出空间。Java虚拟机中垃圾回收是一种自动化的过程,它不需要程序员手动干预,但是程序员可以通过代码的方式对垃圾回收过程进行影响。 Java垃圾回收算法 在Java虚拟机对内存进行垃圾回收时,需要选择一个合适的垃圾…

    Java 2023年5月26日
    00
  • Knife4j 3.0.3 整合SpringBoot 2.6.4的详细过程

    下面是 “Knife4j 3.0.3 整合 SpringBoot 2.6.4 的详细过程”: 首先,需要确保我们的项目中已经添加了 SpringBoot 2.6.4 的依赖。可以在 pom.xml 文件中添加以下依赖: <dependency> <groupId>org.springframework.boot</groupId…

    Java 2023年5月19日
    00
  • 基于String不可变字符与StringBuilder可变字符的效率问题

    当需要在应用程序中频繁操作字符串时,我们可以使用 String 类的字符串常量或 StringBuilder 可变字符类。虽然两种方式都可以操作字符,但它们之间具有不同的性能和效率。 String 类创建的字符串是不可变的字符序列。每次更改字符串时,都会创建一个新的字符串对象,因此需要更多的系统开销和内存来存储字符串,这会影响程序的性能。如果应用程序需要频繁…

    Java 2023年5月27日
    00
  • SpringBoot项目中使用AOP的方法

    下面我来为您详细讲解在SpringBoot项目中使用AOP的方法。 首先,您需要在pom.xml文件中添加AOP的依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop&lt…

    Java 2023年5月15日
    00
  • Java throw关键字的作用是什么?

    Java中的throw关键字是用于手动抛出异常的关键字,可以使得程序员在遇到特殊情况时自己构造出一个异常对象并抛出,从而中断程序的正常流程,进入异常处理。 throw关键字的语法格式为: throw throwableInstance; 其中throwableInstance可以是任何一个继承自Throwable的Java类的对象。根据Java的异常处理机制…

    Java 2023年4月27日
    00
  • springboot~关于md5签名引发的问题

    事实是这样的,我有个接口,这个接口不能被篡改,于是想到了比较简单的md5对url地址参数进行加密,把这个密码当成是sign,然后服务端收到请求后,使用相同算法也生成sign,两个sign相同就正常没有被篡改过。 问题的出现 接口中的参数包括userId,extUserId,时间,其中extUserId字符编码,中间会有+这种符号 有些用户使用签名接口正常 有…

    Java 2023年4月23日
    00
  • Java 数组转List的四种方式小结

    Java 数组转 List 的四种方式小结 在 Java 开发中,数组和 List 是非常常见的数据类型。有时我们需要将数组转换成 List 以便进行操作。本文将介绍四种将 Java 数组转换成 List 的常用方法。 方法一:使用 Arrays.asList() Arrays 类提供了一个 asList() 方法,可以将数组转换成 List。 SomeTy…

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