关于Spring中声明式事务的使用详解

关于Spring中声明式事务的使用详解

什么是声明式事务?

在Spring中,事务是指一组需要保证数据完整性和一致性的数据库操作。 在进行事务处理时,必须保证多个操作的原子性,即所有操作都能够全部成功或全部失败。

Spring中的声明式事务是基于AOP实现的,通过对方法进行拦截,在方法执行前后加上事务的开始和结束语句,来实现事务的管理。这样即使开发人员忘记在方法中手动添加事务的开始和结束语句,也可以确保方法能够在事务环境中执行,保证数据的完整性和一致性。

如何使用声明式事务?

配置文件中的声明式事务

在Spring中,我们可以在配置文件中通过<tx:advice><aop:config>标签声明式定义事务。下面是一个示例:

<bean id="userService" class="com.example.UserService" />

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

<tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
        <tx:method name="save" propagation="REQUIRED" rollback-for="Exception"/>
        <tx:method name="update" propagation="REQUIRED" rollback-for="Exception"/>
        <tx:method name="delete" propagation="REQUIRED" rollback-for="Exception"/>
        <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="userServicePointcut" expression="execution(* com.example.UserService.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="userServicePointcut"/>
</aop:config>

上述代码中,我们首先声明了一个名为txManager的事务管理器,以管理使用Spring声明式事务的数据源。然后我们使用<tx:attributes>标签定义了事务传播机制、是否只读等Transaction Attributes信息,接着我们在<tx:advice>标签中引入刚才声明的事务管理器,并且将之前定义好的<tx:attributes>添加进去。最后使用<aop:config>标签进行切面配置,并在<aop:pointcut>标签中定义所需要拦截的方法,即com.example.UserService中的所有方法。最后通过<aop:advisor>标签将拦截器和切面关联起来。

在这个示例中,我们通过如上的配置,可以对UserService中的所有公有方法进行事务管理。当我们调用saveupdatedelete等写操作时,将会被Spring事务拦截并在方法执行前开启事务,在方法执行后进行事务提交或回滚。

使用注解的声明式事务

注解式事务是一种使用注解的方式声明事务的方式。相比于xml配置的方式,这种方式更加简洁明了。

@Service
public class UserService {
    @Autowired
    private UserDao userDao;

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void save(User user) throws Exception {
        userDao.save(user);
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void update(User user) throws Exception {
        userDao.update(user);
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void delete(Long userId) throws Exception {
        userDao.delete(userId);
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS, readOnly = true)
    public User findUserById(Long userId) throws Exception {
        return userDao.findUserById(userId);
    }
}

上述代码中我们在UserService类中对方法进行了注解式事务的声明,通过@Transactional注解的propagation属性来确定事务传播机制,readOnly属性来指明方法是否为只读操作。我们还可以通过rollbackFornoRollbackFor属性来指明哪些异常需要回滚事务,哪些异常不需要回滚事务。

实例演示

在本次演示中,我们将使用Spring、MySQL和SpringMVC实现一个简单的增删改查功能。具体的示例代码参见https://github.com/LZxiaozhi/spring-transaction-demo

步骤

  1. 创建SpringMVC项目。
  2. 引入相关依赖。
  3. 在配置文件中配置MySQL数据源。
  4. 创建DAO层和Service层。
  5. 在Controller层中进行测试。

代码示例

  • 配置文件
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false&amp;serverTimezone=UTC&amp;allowPublicKeyRetrieval=true"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</bean>

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

<tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
        <tx:method name="save" propagation="REQUIRED" rollback-for="Exception"/>
        <tx:method name="update" propagation="REQUIRED" rollback-for="Exception"/>
        <tx:method name="delete" propagation="REQUIRED" rollback-for="Exception"/>
        <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="userServicePointcut" expression="execution(* com.example.service.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="userServicePointcut"/>
</aop:config>
  • Service层
@Service
public class UserService {
    @Autowired
    private UserDao userDao;

    public List<User> findAll() {
        return userDao.findAll();
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void save(User user) throws Exception {
        userDao.add(user);
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void update(User user) throws Exception {
        userDao.update(user);
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void delete(Long id) throws Exception {
        userDao.delete(id);
    }
}
  • Controller层
@Controller
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/")
    public String index(Model model) {
        List<User> userList = userService.findAll();
        model.addAttribute("userList", userList);
        return "index";
    }

    @GetMapping("/add")
    public String add() {
        return "add";
    }

    @PostMapping("/add")
    public String save(User user) throws Exception {
        userService.save(user);
        return "redirect:/";
    }

    @GetMapping("/edit/{id}")
    public String edit(@PathVariable Long id, Model model) throws Exception {
        User user = userService.findById(id);
        model.addAttribute("user", user);
        return "edit";
    }

    @PostMapping("/edit/{id}")
    public String update(@PathVariable Long id, User user) throws Exception {
        user.setId(id);
        userService.update(user);
        return "redirect:/";
    }

    @GetMapping("/delete/{id}")
    public String delete(@PathVariable Long id) throws Exception {
        userService.delete(id);
        return "redirect:/";
    }
}

结论

在以上演示示例中,我们通过使用Spring中的声明式事务实现了数据的增删改查功能。

声明式事务的使用需要开发人员对AOP、事务传播机制等基本概念有一定的理解;在配置中需要注意propagationreadOnly等属性的值得合理配置;在实际应用中,我们可以通过注解和xml配置两种方式声明式的配置Spring事务。

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

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

相关文章

  • java的Jackson将json字符串转换成泛型List

    转换JSON字符串成Java对象是Java程序中经常需要做的一个任务。有很多开源库能够帮助我们完成这一任务,如Jackson。Jackson 是一个高效的 JSON 处理器,能够将 JSON 字符串解析成 Java 对象。 Jackson 支持将 JSON 转换成 Java 对象,也支持将 JSON 转换成泛型 List,本篇攻略将介绍 Jackson 将 …

    Java 2023年5月26日
    00
  • java算法实现预测双色球中奖号码

    Java算法实现预测双色球中奖号码攻略 1. 背景介绍 双色球是一种中国彩票游戏,由中国福利彩票发行中心组织销售。双色球每周进行两次摇奖,每次从1至33个红色数字球中随机摇出6个,并从1至16个蓝色数字球中随机摇出1个,共7个数字。 对于热爱双色球彩票的玩家来说,预测开奖号码是程序化选号的一种选择。本文主要介绍Java算法实现预测双色球中奖号码的完整攻略和示…

    Java 2023年5月19日
    00
  • java的jps命令使用详解

    Java的jps命令使用详解 jps命令是Java提供的一个实用工具,用于显示当前机器上所有正在运行的Java进程以及它们的PID(进程标识符)和类名。它通常被用于快速查看Java进程的运行状态,因此是Java程序调试和性能优化的重要工具之一。 语法 jps 命令的基本语法如下: jps [ options ] [ hostid ] 其中,hostid 指定…

    Java 2023年5月26日
    00
  • 如何进行Java网络编程?

    当我们需要在Java程序中进行网络通信时,需要使用Java的网络编程技术。Java提供了Socket编程API,可以用Socket编程实现基于TCP或UDP协议的网络通信。下面是进行Java网络编程的完整使用攻略: 1. 创建Socket对象 Socket类代表了客户端与服务器之间的套接字,客户端可以使用它连接到服务器。在Java中创建Socket对象的语法…

    Java 2023年5月11日
    00
  • mybatis3使用@Select等注解实现增删改查操作

    下面是使用MyBatis3的注解@Select等实现增删改查操作的完整攻略。 首先,我们需要在项目的pom.xml文件中添加MyBatis3的依赖,如下所示: <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifact…

    Java 2023年5月20日
    00
  • Springboot实现高吞吐量异步处理详解(适用于高并发场景)

    Spring Boot实现高吞吐量异步处理详解 在高并发场景下,异步处理是提高系统吞吐量的一种有效方式。Spring Boot提供了多种异步处理方式,本文将详细介绍如何使用Spring Boot实现高吞吐量异步处理,并提供两个示例。 异步处理方式 Spring Boot提供了多种异步处理方式,包括: 使用@Async注解实现异步方法调用。 使用Complet…

    Java 2023年5月15日
    00
  • Java获取精确到秒的时间戳方法

    当我们需要获取当前时间的时间戳时,可以使用Java提供的System.currentTimeMillis()方法,该方法返回的是自1970年1月1日零时零分零秒(GMT/UTC)以来的毫秒数,也就是常说的Unix时间戳。但有时候我们需要获取精确到秒的时间戳,可以通过以下两种方式实现。 1. 使用Java 8中的Instant类 Java 8中新增了一个新的日…

    Java 2023年5月20日
    00
  • 基于javaMybatis存进时间戳的问题

    那我来详细讲解一下关于“基于Java Mybatis存进时间戳的问题”的攻略。 问题背景 在使用Java Mybatis框架进行MySQL数据库操作时,我们有时需要将时间信息存储为时间戳(长整型),然后进行操作。但在实际操作中,我们有可能遇到时间戳值存储不对的问题,导致数据不正确。 解决方案 方案1:使用注解方式进行时间戳的映射 在Mybatis的实体映射中…

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