28.基于注解的声明式事务

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

基于注解的声明式事务

准备工作

将之间的使用的数据库表t_user更改为t_user1,使用的依赖和对应的jdbc.properties不变即可

准备数据库

BookSql.sql

	CREATE TABLE `t_book` (
		`book_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
		`book_name` varchar(20) DEFAULT NULL COMMENT '图书名称',
		`price` int(11) DEFAULT NULL COMMENT '价格',
		`stock` int(10) unsigned DEFAULT NULL COMMENT '库存(无符号)', -- unsigned代表插入的数值必须大于或者等于0
		PRIMARY KEY (`book_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
	insert into `t_book`(`book_id`,`book_name`,`price`,`stock`) values (1,'斗破苍穹',80,100),(2,'斗罗大陆',50,100);

	CREATE TABLE `t_user` ( 
        `user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
		`username` varchar(20) DEFAULT NULL COMMENT '用户名',
		`balance` int(10) unsigned DEFAULT NULL COMMENT '余额(无符号)',
		PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
	insert into `t_user`(`user_id`,`username`,`balance`) values (1,'admin',50);

创建组件

BookController.java

package com.atguigu.tx.controller;

import com.atguigu.tx.service.BookService;
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);
    }
}

BookDao.java

package com.atguigu.tx.dao;

public interface BookDao {
    /*根据图书的id查询图书的价格*/
    Integer getPriceByBookId(Integer bookId);
    /*更新图书的库存*/
    void updateStock(Integer bookId);
    /*更新用户的余额*/
    void updateBalance(Integer userId, Integer price);
}

BookDaoImpl.java

package com.atguigu.tx.dao.Impl;

import com.atguigu.tx.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class BookDaoImpl implements BookDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

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

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

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

BookService.java

package com.atguigu.tx.service;

public interface BookService {

    void buyBook(Integer bookId, Integer userId);
}

BookServiceImpl.java

package com.atguigu.tx.service.impl;

import com.atguigu.tx.dao.BookDao;
import com.atguigu.tx.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private BookDao bookDao;

    @Override
    public void buyBook(Integer bookId, Integer userId) {
        //这里每个sql语句的事务都是独立的

        //查询图书的价格
        Integer price = bookDao.getPriceByBookId(bookId);
        //更新图书的库存
        bookDao.updateStock(bookId);
        //更新用户的余额
        bookDao.updateBalance(userId, price);
    }
}

所有组件文件:

28.基于注解的声明式事务,SSM,数据库,java,开发语言

Spring配置文件

spring-tx-annotation.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:component-scan base-package="com.atguigu.tx"/>

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

    <!-- 配置数据源 -->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${jdbc.url}"/>
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

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

测试无事务情况

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

假设用户id为1的用户,购买id为1的图书,用户余额为50,而图书价格为80,购买图书之后,用户的余额为-30,数据库中余额字段设置了无符号,因此无法将-30插入到余额字段,此时执行sql语句会抛出SQLException

TxByAnnotationTest.java

package com.atguigu.TxByAnnotation.test;

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

//设置当前测试类的运行环境-->在spring的测试环境中运行,就可以通过注入的方式直接获取IOC容器中的bean
@RunWith(SpringJUnit4ClassRunner.class)
//设置Spring测试环境的配置文件
@ContextConfiguration("classpath:spring-tx-annotation.xml")
public class TxByAnnotationTest {

    @Autowired
    private BookController bookController;

    @Test
    public void testBuyBook(){
        //定义用户的余额为unsigned,但是用户余额只有50,余额不足以购买80的书
        //由于一个sql语句独占一个事务,"库存(stock)"减少了,但是"付款"失败了
        bookController.buyBook(1,1);
    }
}

28.基于注解的声明式事务,SSM,数据库,java,开发语言

因为没有添加事务,图书的库存更新了,但是用户的余额没有更新。显然这样的结果是错误的,购买图书是一个完整的功能,更新库存和更新余额要么都成功要么都失败

实现事务功能

spring-tx-annotation.xml

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

    <!--开启事务的注解驱动-->
    <!--通过transaction-manager将事务管理器和事务的注解驱动联系起来,默认为transactionManager(前面使用的默认id,所以该属性可以省略)-->
    <tx:annotation-driven transaction-manager="transactionManager"/>

28.基于注解的声明式事务,SSM,数据库,java,开发语言

@Transactional注解标识的位置

  • @Transactional标识在方法上,则只会影响该方法
  • @Transactional标识的类上,则会影响类中所有的方法

因为service层表示业务逻辑层,一个方法表示一个完成的功能,因此处理事务一般在service层处理在BookServiceImpl的buybook()添加注解@Transactional

BookServiceImpl.java

    @Override
    @Transactional //注解的这个方法中的所有sql语句是一个事务
    public void buyBook(Integer bookId, Integer userId) {
        //查询图书的价格
        Integer price = bookDao.getPriceByBookId(bookId);
        //更新图书的库存
        bookDao.updateStock(bookId);
        //更新用户的余额
        bookDao.updateBalance(userId, price);
    }

此时再运行就不会出现只扣了"库存(stock)",没有"付款"的情况文章来源地址https://www.toymoban.com/news/detail-606673.html

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

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

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

相关文章

  • 基于Spring注解 + MyBatis + Servlet 实现数据库交换的小小Demo

    配置数据库连接信息 db.properties 配置web.xml 配置logback.xml配置文件 配置applicationContext.xml 里面的bean 配置myBatis核心配置文件mybatis-config.xml 创建实体类对象User 创建LoginServlet响应前端的数据 创建UserService 接口 创建UserMapper接口 创建UserServiceImpl 接口实现类 按照这样的方式进行拼接

    2024年02月02日
    浏览(85)
  • 实习记录小程序|基于SSM的实习记录小程序设计与实现(源码+数据库+文档)

    知识管理 目录 基于SSM的习记录小程序设计与实现 一、前言 二、系统设计 三、系统功能设计  1、小程序端: 2、后台 四、数据库设计  五、核心代码  六、论文参考 七、最新计算机毕设选题推荐 八、源码获取:   博主介绍 :✌️大厂码农|毕设布道师,阿里云开发社区乘

    2024年04月11日
    浏览(75)
  • Java项目:基于SSM框架实现同城蔬菜配送管理系统(SSM+B/S架构+源码+数据库+毕业论文)

    本项目是一套ssm825基于SSM框架实现同城蔬菜配送管理系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或idea 确保可以运行! 该系统功能

    2024年01月25日
    浏览(58)
  • 基于SSM微信小程序物流仓库管理系统设计与实现(lw+数据库+讲解等)

    💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 2023-2024年最值得选的微信小程序毕业设计

    2024年02月21日
    浏览(58)
  • [Linux][CentOs][Mysql]基于Linux-CentOs7.9系统安装并配置开机自启Mysql-8.0.28数据库

    目录 一、准备工作:获取安装包和相应工具 (一)所需安装包 (二)安装包下载链接 (三)在服务器上创建文件夹并上传安装包 二、安装MySql (一)删除系统自带的mariadb (二)安装MySQL依赖包libaio (三)创建MySQL组和用户并设置密码 (四)将MySQL目录的权限授给MySQL用户

    2024年03月25日
    浏览(62)
  • 外卖小程序|基于Java+SSM+Uniapp的外卖微信小程序设计与实现(源码+数据库+文档)

    外卖小程序目录 目录 基于微信小程序的外卖订餐系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户微信端功能模块 2、管理员服务端功能模块 3、商家务端功能模块 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐  八、

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

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

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

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

    2024年01月25日
    浏览(52)
  • Java项目:ssm框架基于spring+springmvc+mybatis框架的民宿预订管理系统设计与实现(ssm+B/S架构+源码+数据库+毕业论文)

    本项目是一套ssm827基于SSM框架的民宿预订管理系统设计与实现,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse 确保可以运行! 该系统功能

    2024年01月22日
    浏览(84)
  • 面试好题:@Transactional声明式事务注解什么时候会失效?

    今天来分享一道比较有意思的面试题,“@Transactional声明式事务注解什么时候会失效?”。 对于这个问题,我们一起看看考察点和比较好的回答吧!     这个问题就是面试官想考察我们对@Transactional注解有没有深刻的认识,以及日常开发中是否善于积累,认真思考。 下面我

    2024年02月09日
    浏览(39)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包