15、Spring之基于xml的声明式事务

这篇具有很好参考价值的文章主要介绍了15、Spring之基于xml的声明式事务。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

阅读本文前,建议先阅读Spring之基于注解的声明式事务

15.1、环境搭建

创建名为spring_transaction_xml的新module,过程参考13.1节

15.1.1、配置打包方式和依赖

15、Spring之基于xml的声明式事务

注意:比起基于注解的声明式事务,基于xml的声明式事务还需要额外引入spring-AOP的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.rain</groupId>
    <artifactId>spring_transaction_xml</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>

        <!-- Spring IOC相关 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.1</version>
        </dependency>

        <!-- Spring 持久化层相关 -->
        <!-- Spring 在执行持久化层操作、与持久化层技术进行整合过程中,需要使用orm、jdbc、tx三个jar包 -->
        <!-- 导入 orm 包就可以通过 Maven 的依赖传递性把其他两个也导入 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>5.3.1</version>
        </dependency>

        <!-- Spring 测试相关 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.1</version>
        </dependency>

        <!-- spring-AOP的依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.3.1</version>
        </dependency>

        <!-- junit测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <!-- MySQL驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>

        <!-- 数据源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.31</version>
        </dependency>
    </dependencies>

</project>

15.1.2、创建jdbc.properties文件

15、Spring之基于xml的声明式事务

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

15.1.3、创建Spring的配置文件

15、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"
       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">

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

    <!-- 配置数据源 -->
    <bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource">
        <!--通过${key}的方式访问外部属性文件的value-->
        <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>

    <!-- 配置 JdbcTemplate -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!-- 装配数据源 -->
        <property name="dataSource" ref="datasource"></property>
    </bean>

</beans>

15.1.4、创建持久层接口BookDao及其实现类

15、Spring之基于xml的声明式事务

package org.rain.spring.dao;

/**
 * @author liaojy
 * @date 2023/9/3 - 17:34
 */
public interface BookDao {

    /**
     * 查询图书的价格
     * @param bookId
     * @return
     */
    Integer getPriceByBookId(Integer bookId);

    /**
     * 更新图书的库存
     * @param bookId
     */
    void updateStockOfBook(Integer bookId);

    /**
     * 更新用户的余额
     * @param userId
     * @param price
     */
    void updateBalanceOfUser(Integer userId,Integer price);

}

15、Spring之基于xml的声明式事务

package org.rain.spring.dao.impl;

import org.rain.spring.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

/**
 * @author liaojy
 * @date 2023/9/3 - 17:36
 */
@Repository
public class BookDaoImpl implements BookDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public Integer getPriceByBookId(Integer bookId) {
        String sql = "select price from t_book where book_id = ?";
        Integer price = jdbcTemplate.queryForObject(sql, Integer.class,bookId);
        return price;
    }

    public void updateStockOfBook(Integer bookId) {
        String sql = "update t_book set stock = stock -1 where book_id = ?";
        jdbcTemplate.update(sql, bookId);
    }

    public void updateBalanceOfUser(Integer userId, Integer price) {
        String sql = "update t_user set balance = balance - ? where user_id = ?";
        jdbcTemplate.update(sql,price,userId);
    }

}

15.1.5、创建业务层接口BookService及其实现类

15、Spring之基于xml的声明式事务

package org.rain.spring.service;

/**
 * @author liaojy
 * @date 2023/9/3 - 17:52
 */
public interface BookService {

    void buyBook(Integer bookId,Integer userId);

}

15、Spring之基于xml的声明式事务

package org.rain.spring.service.impl;

import org.rain.spring.dao.BookDao;
import org.rain.spring.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author liaojy
 * @date 2023/9/3 - 17:53
 */
@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private BookDao bookDao;

    public void buyBook(Integer bookId, Integer userId) {

        //查询图书的价格
        Integer price = bookDao.getPriceByBookId(bookId);

        //更新图书的库存
        bookDao.updateStockOfBook(bookId);

        //更新用户的余额
        bookDao.updateBalanceOfUser(userId,price);

    }
}

15.1.6、创建控制层BookController

15、Spring之基于xml的声明式事务

注意:因为控制层没用到接口,所以方法的访问修饰符要手动设置

package org.rain.spring.controller;

import org.rain.spring.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 * @author liaojy
 * @date 2023/9/3 - 17:54
 */
@Controller
public class BookController {

    @Autowired
    private BookService bookService;

    public void buyBook(Integer bookId, Integer userId){
        bookService.buyBook(bookId,userId);
    }

}

15.1.7、配置对注解组件的扫描

15、Spring之基于xml的声明式事务

    <!--扫描注解组件-->
    <context:component-scan base-package="org.rain.spring"></context:component-scan>

15.2、基于xml事务的实现

15.2.1、配置事务管理器

15、Spring之基于xml的声明式事务

<!--配置事务管理器-->
    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 装配要进行事务管理的数据源 -->
        <property name="dataSource" ref="datasource"></property>
    </bean>

15.2.2、配置事务通知

15、Spring之基于xml的声明式事务

注意:tx:advice标签导入的名称空间需要 tx 结尾的那个

    <!--
        tx:advice标签:配置事务通知
            id属性:给事务通知标签设置唯一标识,便于引用
            transaction-manager属性:通过id引用对应的事务管理器
    -->
    <tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager"></tx:advice>

15.2.3、配置事务通知作用到连接点

15、Spring之基于xml的声明式事务

    <aop:config>
        <!--
            通过切入点表达式,将事务通知作用到连接点
        -->
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* org.rain.spring.service.impl.*.*(..))"></aop:advisor>
    </aop:config>

15.2.4、配置事务通知的属性

15、Spring之基于xml的声明式事务

注意:不使用tx:method标签指定的方法是不会使用事务的,为了让切入点表达式的所有方法都使用到事务,可以使用*通配符:
<tx:method name="*"/>

        <tx:attributes>
            <!--
                tx:method标签:配置使用事务的方法
                    name属性:指定用事务的方法名,可以使用星号代表多个字符
            -->
            <tx:method name="buyBook"/>
        </tx:attributes>

15.3、测试事务的效果

15.3.1、创建测试类

模拟场景:

  • 用户购买图书,先查询图书的价格,再更新图书的库存和用户的余额

  • 假设id为1的用户(余额为50),购买id为1的图书(价格为80)

  • 购买图书之后,用户的余额应为-30;但由于数据库中余额字段设置了无符号,因此无法将-30插入到余额字段;
    此时执行更新用户余额的sql语句会抛出异常

15、Spring之基于xml的声明式事务

package org.rain.spring.test;

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

/**
 * @author liaojy
 * @date 2023/9/4 - 0:20
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-tx-xml.xml")
public class TxByXml {

    @Autowired
    private BookController bookController;

    @Test
    public void testBuyBook(){
        bookController.buyBook(1,1);
    }

}

15.3.2、执行前的数据

15、Spring之基于xml的声明式事务

此时id为1的图书库存为100

15、Spring之基于xml的声明式事务

此时id为1的用户余额为50

15.3.3、执行时的异常

15、Spring之基于xml的声明式事务

15.3.3、执行后的数据

15、Spring之基于xml的声明式事务

由于使用了Spring的声明式事务,更新(图书)库存和更新(用户)余额,要么都成功,要么都失败;

本例属于都失败,所以(图书)库存和(用户)余额都没有变化

15、Spring之基于xml的声明式事务

15.4、配置事务的属性

15、Spring之基于xml的声明式事务

事务属性的详细作用,请参考14.5节文章来源地址https://www.toymoban.com/news/detail-693147.html

 <!-- rollback-for属性:设置回滚的异常 -->
 <!-- no-rollback-for属性:设置不回滚的异常 -->
 <!-- isolation属性:设置事务的隔离级别 -->
 <!-- timeout属性:设置事务的超时属性 -->
 <!-- propagation属性:设置事务的传播行为 -->
 <tx:method name="save*" read-only="false" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
 <tx:method name="update*" read-only="false" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
 <tx:method name="delete*" read-only="false" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>

到了这里,关于15、Spring之基于xml的声明式事务的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring 事务(编程式事务、声明式事务@Transactional、事务隔离级别、事务传播机制)

    本篇重点总结: 在 Spring 项目中使用事务,有两种方式:编程式手动操作和声明式自动提交,声明式自动提交使用最多,只需要在方法上添加注解 @Transactional 设置事务的隔离级别 @Transactional(isolation = Isolation.SERIALIZABLE),Spring 中的事务隔离级别有5种 设置事务的传播机制 @Tra

    2024年02月03日
    浏览(42)
  • Spring声明式事务(Spring学习笔记十三)

            不推荐使用编程式事务  在Spring-dao.xml中配置声明式事务  结合aop实现事务的织入 分两步         第一步:          第二步:

    2024年04月10日
    浏览(38)
  • Spring 声明式事务 @Transactional(基本使用)

            声明式事务的实现很简单,只需要在需要事务的⽅法上添加 @Transactional 注解就可以实现了.⽆需⼿动开启事务和提交事务,进⼊⽅法时⾃动开启事务,⽅法执⾏完会⾃动提交事务,如果中途发⽣了 没有处理的异常会⾃动回滚事务.         废话不多说,直接看代码实现,

    2024年01月23日
    浏览(48)
  • Spring Boot原理分析(四):声明式事务

    Spring 提供了多种管理事务的方式,包括编程式事务管理和声明式事务管理两种方式。下面分别介绍这两种方式及其实现方式: 编程式事务管理是通过编写代码来手动管理事务。它需要在事务的开始和结束时,通过编程方式来控制事务的提交和回滚。Spring 提供了 PlatformTransa

    2024年02月17日
    浏览(46)
  • Spring 事务的相关配置、传播行为、隔离级别及注解配置声明式事务

    目录 一、事务的相关配置 1. 添加测试标签 2. 添加对应方法 3. 测试 二、事务的传播行为 三、事务的隔离级别 四、注解配置声明式事务 1. 注册事务注解驱动 2. 加上注解 3. 配置类代替xml文件中的注解事务支持 4. 测试 往期专栏文章相关导读  1. Maven系列专栏文章 2. Mybatis系列专

    2024年02月08日
    浏览(44)
  • Spring 声明式事务不生效的问题如何解决

    Spring 声明式事务不生效的问题如何解决 Spring 的声明式事务通常使用 @Transactional 注解来实现。如果你发现声明式事务不生效,可能有几个原因导致这种情况。以下是一些可能的解决方法: 确保配置正确 : 确保在 Spring 的配置文件(如 applicationContext.xml)中启用了事务管理器

    2024年02月21日
    浏览(34)
  • Spring 声明式事务讲解,和 @Transactional注解的用法

    目录 一、Spring框架介绍 二、什么是声明式事务 三、如何解决并发性事务问题 四、@Transactional注解的用法 Spring框架是一个开源的Java应用程序开发框架,旨在简化企业级Java应用程序的开发。它提供了一种轻量级的、全面的编程和配置模型,可以帮助开发人员构建可扩展、模块

    2024年01月25日
    浏览(48)
  • Spring 声明式事务 @Transactional(详解)【面试重点,小林出品】

            关于 @Transactional 注解的基本使用,推荐看Spring 声明式事务 @Transactional(基本使用)         本篇博客主要学习 @Transactional 注解当中的三个常⻅属性:         1. rollbackFor:异常回滚属性.指定能够触发事务回滚的异常类型.可以指定多个异常类型         2. Iso

    2024年01月25日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包