spring —— 事务管理器

事务管理主要针对数据源进行操作:在数据库方面,通过 TransactionManager 事务管理器进行管理,表明一旦出现错误,该数据源的所有数据全部复原。那么数据库如何判断是否发生了错误呢?这就需要在代码方面,通过 @Transactional 注解管理相应的方法,表示一旦该方法出现错误,那么由该方法调用的数据就要执行回滚。

一、spring-config.xml 文件配置

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--扫描组件-->
    <context:component-scan base-package="com.spring.book"></context:component-scan>
    <!--引入外部文件-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
    <!--使用druid工具配置数据源-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${jdbc.url}"></property>
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="username" value="${jdbc.user}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
    <!--将数据源作为属性传入JDBCTemplate对象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="druidDataSource"></property>
    </bean>
    <!--将数据源作为属性传入DataSourceTransactionManager事务管理器对象-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="druidDataSource"></property>
    </bean>
    <!--启用事务管理器注解-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>

二、数据库

balance 设置为"无符号",也就是不能为负数。

三、java 代码

Dao 层类:

java 复制代码
package com.spring.book;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component
public class BookDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;

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

    public void updateStock(Integer bookId){
        String sql = "update book set stock=stock-1 where bookid=?";
        jdbcTemplate.update(sql, bookId);
    }

    public void updateBalance(Integer userId, Integer price){
        String sql = "update user set balance=balance-? where userid=?";
        jdbcTemplate.update(sql, price, userId);
    }
}

Service 类:

java 复制代码
package com.spring.book;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BookService {
    @Autowired
    private BookDao bookDao;

    public void buyBook(Integer bookId, Integer userId){
        Integer price=bookDao.getPriceByBookId(bookId);
        bookDao.updateStock(bookId);
        bookDao.updateBalance(userId,price);
    }
}

Controller 类:

java 复制代码
package com.spring.book;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class BookController {
    @Autowired
    private BookService bookService;

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

测试类:

java 复制代码
import com.spring.book.BookController;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.transaction.annotation.Transactional;

@SpringJUnitConfig(locations = "classpath:bean-jdbc.xml")
public class TxByAnnotationTest {
    @Autowired
    private BookController bookController;
    @Test
    @Transactional
    public void testBuyBook(){
        bookController.buyBook(1,1);
    }
}

四、说明

该案例模拟 user 从 book 列表中买书的过程,如果交易成功,book 的库存减少 1,user 的资金减少相应的价格。如果不添加事务管理的话,Dao 层的各个方法是互不影响的,会出现资金不减少,但库存减少的情况,因此需要将这些方法作为一个统一的整体。此时可以将 @Transactional 注解添加在 Service 层、Controller 层或者 Test 层均可实现效果,也就是说受到 @Transactional 注解影响到的方法一旦出现错误,那么该方法调用的数据都将恢复原状。而究竟是哪些数据,则由 spring-config.xml 配置文件的 TransactionManager 确定。

相关推荐
molaoye21 分钟前
win10下安装MySQL 8.0.*实录
数据库·mysql
麻雀聊技术24 分钟前
一重启 AI 就失忆?用 Spring AI + PostgreSQL 3步搞定“长期记忆”持久化(附完整代码)
java·spring·openai
千舟软件32 分钟前
千舟软件介绍 | 顺便聊聊我们做了哪些产品
大数据·数据库·科技·小程序·业界资讯
番茄炒鸡蛋加糖1 小时前
中级核心技术1--MySQL/Java 并发
java·数据库·mysql
he___H1 小时前
Spring-Configur注解
java·spring
戴西软件1 小时前
戴西CAxWorks.VPG车辆工程仿真软件技术解析(上)——安全仿真体系的自动化构建
运维·网络·数据库·人工智能·算法·安全·自动化
灯澜忆梦2 小时前
【MySQL10】进阶篇 | 索引_#1
数据库·sql·mysql
敲上瘾2 小时前
redis常用数据类型与操作方法
数据结构·数据库·redis·缓存
铃木之影2 小时前
Java 版本 RAG 示例(Spring AI + Milvus)
java·人工智能·spring
OceanWaves19933 小时前
mysql 5.7.29 主从同步配置
数据库·mysql·adb