2019独角兽企业重金招聘Python工程师标准>>>

Spring的事务管理  
事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性,在开发中,我们是经常遇到的两个字,而且在安卓开发中也是频繁出现的。

那么在Spring中,对于jdbc的支持是怎样的呢?在这里暂且先抛弃Hibernate,Mybatis框架的使用,看看传统的Spring中对数据库的操作,其实,后面的框架也是一样的逻辑道理的。

业务需求:一个数据库中,有三张表,分别是:

用户资料表:表内包含 id, username , price(用户的账户余额)三个字段

书籍表:表内包含 id , bookname , bookprice 三个字段

书店表:表内包含 bookid , count(对应bookid书籍的剩余数量)

需求:

  • 根据书的编号查找书的价格
  • 更新书的库存
  • 更新用户的账户余额

那么先根据需求写一个接口  BookShopI

public interface BookShopI {

/**
     * 根据书的编号查找书的价格
     * @param id 书的编号
     * @return
     */
    int findBookPriceById(String id);
    
    /**
     * 更新书的库存
     * @param id 书的编号
     */
    void updateBookStore(String id);
    
    /**
     * 更新用户的账户余额
     * @param userName 用户名
     * @param price        余额
     */
    void updateUserAccount(String userName,int price);
}

有了接口那么我们就写个基于此接口的实现类

@Repository("bookShop")
public class BookShopImpl implements BookShopI {

@Autowired
    private JdbcTemplate jdbcTemplate;

@Override
    public int findBookPriceById(String id) {
        String sql = "select bookprice from book where id = ? ";
        return jdbcTemplate.queryForObject(sql, Integer.class, id);
    }

@Override
    public void updateBookStore(String id) {
        // 先查找数据库的的剩余的库存,若等于0则抛出库存不足的异常(前提是用户每次购买一本的情况下)
        String checkSql = "select count from book_store where bookid = ?";
        Integer count = jdbcTemplate.queryForObject(checkSql, Integer.class, id);
        if (count == 0) {
            throw new BookStoreException("库存不足");
        }
        String sql = "update book_store set count = count - 1 where bookid = ?";
        jdbcTemplate.update(sql, id);

}

@Override
    public void updateUserAccount(String userName, int price) {
        //先查找数据库的的用户剩余的余额,若小于所要支付的金钱则抛出余额不足的异常
        String checkSql = "select price from account where username = ?";
        Integer userPrice = jdbcTemplate.queryForObject(checkSql, Integer.class, userName);
        if (userPrice < price) {
            throw new UserPriceException("余额不足");
        }
        String sql = "update account set price = price - ? where username = ?";
        jdbcTemplate.update(sql, price, userName);

}

}

其中实现类中的两个异常类 BookStoreException 和 UserPriceException 都是一个继承RuntimeException的java类,然后实现父类的构造方法,在这就不贴出来了。

一个服务接口: UserByBookServiceI

public interface UserByBookServiceI {
    
    /**
     * 用户买书
     * @param UserName 用户名
     * @param bookId 书的编号
     */
    void byBook(String UserName,String bookId);

}

对应接口的实现 UserByBookServiceI :

@Service("userByBookService")
public class UserByBookServiceImpl implements UserByBookServiceI {
    
    @Autowired
    private BookShopI bookShopI;
    
    @Override
    public void byBook(String UserName, String bookId) {
        //1.获取书的单价
        int bookPrice = bookShopI.findBookPriceById(bookId);
        //2.更新书的库存
        bookShopI.updateBookStore(bookId);
        //3.更新用户的余额
        bookShopI.updateUserAccount(UserName, bookPrice);
    }

}

最后是Spring的配置文件

<!-- 导入资源文件 -->
    <context:property-placeholder location="classpath:db.properties"/>
    
    <!-- 自动扫描 -->
    <context:component-scan base-package="com.spring.trans"></context:component-scan>
    
    <!-- 配置c3p0数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${jdbc.user}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
        <property name="driverClass" value="${jdbc.driverClass}"></property>
        <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
        <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
    </bean>
    
    <!-- 配置spring的JdbcTemplate -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

对应的数据库连接信息文件

jdbc.user=root
jdbc.password=
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///testspring
jdbc.initPoolSize=5
jdbc.maxPoolSize=10

最后测试的结果是可以对数据库进行对应的接口操作的,即能修改数据库的信息,并且异常也会捕获,以上都是最基本的Spring对于数据库的操作。

那么问题来了,我们上面为了防止书籍的库存不足或者用于余额不足的情况进行了异常捕获,但实际的操作中,是有问题的,比如当book_store 表当中的某一个书籍的数量不等于0,当一个用户进行购买的时候,数量会自动减1,但是。。。。用户的余额却不足以支付这本书的费用,那么。上面的代码就会造成数据库中书的库存数量减1,用户余额没有减,用户没有购买成功,库存却减少了,显然这是不合理的,这是数据不同步,数据不一致造成的。

因此,在Spring中,Spring的事务JdbcTemplate对此有相应的支持,提供解决办法。

首先在配置文件中添加事务的支持和启用事务的注解(因为是基于注解的操作)

<!-- 配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- 启用事务注解 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

最后在 UserByBookServiceImpl 中添加一个注解

测试观察数据库,即使余额不足,也不会库存减少,当然余额更不会去减少,这就实现了数据的一致和同步性,也体现了事务的作用。关于其内部的实现,还没有去研究,但大概也能知道是aop原理下的事务回滚操作。

转载于:https://my.oschina.net/u/2509896/blog/782845

Spring4 学习系列之——jdbc事务的基本实现和了解相关推荐

  1. Spring4.x()--Spring的Jdbc事务-零配置

    Spring的Jdbc事务-零配置 一.拷贝必要的jar包到工程的lib目录 二.准备数据库表和实体类 创建数据库: create database spring; use spring; 创建表: ...

  2. Spring4.x()-Spring的Jdbc事务-注解

    Spring的Jdbc事务-注解 一.拷贝必要的jar包到工程的lib目录 二.创建spring的配置文件并导入约束 <?xml version="1.0" encoding ...

  3. 老调重弹:JDBC系列 之 JDBC层次结构和基本构成

    前言 最近在研究Mybatis框架,由于该框架基于JDBC,想要很好地理解和学习Mybatis,必须要对JDBC有较深入的了解.所以便把JDBC 这个东东翻出来,老调重弹,好好总结一番,作为自己的笔记 ...

  4. java jdbc事务_Java JDBC事务管理和保存点

    java jdbc事务 Transaction Management in java is required when we are dealing with relational databases ...

  5. 狂神学习系列04:MySQL+JDBC

    狂神学习系列04:MySQL+JDBC 声明: MySQL是基于杜老师的课程所编写,JDBC是基于狂神的课程所编写,本人才疏学浅,内容仅作参考 文章目录 狂神学习系列04:MySQL+JDBC 1. ...

  6. oracle用dual创建临时表,Oracle 学习系列之二(会话与事务级临时表和dual表 )

    一. 会话临时表 --创建会话临时表 create global temporary table tmp_user_session(user_id int, user_name varchar2(20 ...

  7. JDBC学习笔记03【JDBC事务管理、数据库连接池、JDBCTemplate】

    黑马程序员-JDBC文档(腾讯微云)JDBC笔记.pdf:https://share.weiyun.com/Kxy7LmRm JDBC学习笔记01[JDBC快速入门.JDBC各个类详解.JDBC之CR ...

  8. 04-JDBC学习手册:JDBC中使用transaction(事务)编程和Javabean定义

    JDBC中使用 Transaction(事务)编程 1 事务的四大特性 事务是具备以下特征(ACID) 的工作单元: (1) 原子性 事务的原子性指的是,事务中包含的程序作为数据库的逻辑工作单位,它所 ...

  9. Spring4.x()--Jdbc事务-XML

    Spring的Jdbc事务-XML 一.拷贝必要的jar包到工程的lib目录 二.创建spring的配置文件并导入约束 <?xml version="1.0" encodin ...

最新文章

  1. 这次我让你彻底弄懂 RESTful
  2. OPENFIRE支持EMOJI
  3. 1分钟、2束光,3D打印出一座“柏林地标”,精度高于发丝 | Nature
  4. UNICODE与UTF-8的转换
  5. Java虚拟机(JVM)简介
  6. 行人属性数据集pa100k_基于InceptionV3的多数据集联合训练的行人外观属性识别方法与流程...
  7. 马斯克:特斯拉汽车产量今年有望达到50万辆
  8. php 指定时间之前,php计算给定时间之前的函数用法实例
  9. 高程加密lisp程序_lisp修改,怎么把这个加密程序那句去掉,小白求大神帮帮我...
  10. 数据库学习笔记【自学教程】—— 如何建立数据库
  11. 使用密钥文件登录及免密登录服务器方法
  12. ubuntu使用命令设置静态IP地址
  13. OpenGL项目配置GLFW及GLAD
  14. python三维数组读取图片_python读取图片的方式,以及将图片以三维数组的形式输出方法...
  15. SpringBoot系列之(三):启动过程
  16. 关于固态硬盘的一些总结
  17. linux ipp,IPP 文件扩展名: 它是什么以及如何打开它?
  18. vulnhub:THOTH TECH:1靶机
  19. 中心对称图形——平行四边形·复习整理
  20. 学习笔记 自然数e的次方

热门文章

  1. mysql查询每个表的描述_MS SQL SERVER 读取数据库中每个表的描述/注释以及表中字段/列的字段名,字段类型,字段描述/注释/说明等信息...
  2. 傅里叶变换的初级理解二
  3. c# 基于layui的通用后台管理系统_【SpringBoot】三十三、SpringBoot+LayUI后台管理系统开发脚手架...
  4. POJ3522Slim Span(最大边与最小边差值最小的生成树)
  5. java守护线程的特性
  6. (7)操作系统安全机制一
  7. 打工人一次性考过高项的备考指南(52.50.50)
  8. 第13章:项目合同管理--章节真题
  9. 信息系统项目管理师:第8章:项目质量管理-章节真题+解析
  10. Electron中通过process进程对象的api获取CPU、系统位数、环境变量等相关信息