0


Spring:事务

事务

在这里插入图片描述

概述

在数据库中,有时要把多个步骤的命令当作一个整体来运行,这个整体要么全部成功,要么全部失败。这就需要用到事务

在计算机中,事务(Transaction),是访问并可能更新数据库中各种数据项的一个程序执行单元。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。

每个事务都要满足 ACID 特性:

  1. 原子性(Atomicity):表示事务的执行要么全部完成,要么全都不做。一个事务对数据库的所有操作是一个不可分割的操作序列
  2. 一致性(Consistency):表示数据库中的数据总能保持在正确的状态
  3. 隔离性(Isolation):表示事务内部的操作及使用的数据对其他并发事务是隔离的,并发执行的两个或多个事务可以同时运行而互不影响
  4. 持久性(Durability):表示事务一旦完成,对数据库中数据的改变就会永久性保存

@Transactional注解:

  1. propagation属性:设置传播行为,一般在一个存在事务的方法调用另一个也存在事务的方法时使用(当值为Propagation.REQUIRED,使用同一个事务;值为Propagation.REQUIRES_NEW,使用各自事务)
  2. isolation属性:设置隔离级别,一般默认
  3. rollbackFor属性:设置控制回滚,一般默认
  4. readOnly属性:设置事务是否可读,一般查询方法设置为 True ,其余为 False (默认值)
  5. timeout属性:设置事务超时后强制回滚

简单示例:
Spring 的声明式事务(基于注解)
基本逻辑:
获取用户余额、书本价格和数量;
判断余额或数量不足时抛出异常;
用户正常购买书本后,相应减少书本数量和用户余额

首先,创建两张数据表
用户表结构设计:
在这里插入图片描述

书本表结构设计:
在这里插入图片描述

再根据两张数据表定义与之相映射的实体类:

packagecn.edu.springdemo.transactionDemo.model;//用户表publicclassUser{privateint id;privateString name;privateDouble balance;//余额publicUser(){super();}publicUser(int id,String name,Double balance){this.id = id;this.name = name;this.balance = balance;}publicintgetId(){return id;}publicStringgetName(){return name;}publicDoublegetBalance(){return balance;}publicvoidsetId(int id){this.id = id;}publicvoidsetName(String name){this.name = name;}publicvoidsetBalance(Double balance){this.balance = balance;}@OverridepublicStringtoString(){return"User{"+"id="+ id +", name='"+ name +'\''+", balance="+ balance +'}';}}
//书本表packagecn.edu.springdemo.transactionDemo.model;publicclassBook{privateint id;privateString name;//书名privateDouble price;//价格privateint amount;//数量publicBook(){super();}publicBook(int id,String name,Double price,int amount){this.id = id;this.name = name;this.price = price;this.amount = amount;}publicintgetId(){return id;}publicStringgetName(){return name;}publicDoublegetPrice(){return price;}publicintgetAmount(){return amount;}publicvoidsetId(int id){this.id = id;}publicvoidsetName(String name){this.name = name;}publicvoidsetPrice(Double price){this.price = price;}publicvoidsetAmount(int amount){this.amount = amount;}@OverridepublicStringtoString(){return"Book{"+"id="+ id +", name='"+ name +'\''+", price="+ price +", amount="+ amount +'}';}}

接着,在 dao 层定义两个接口,声明相应的方法:

packagecn.edu.springdemo.transactionDemo.dao;publicinterfaceUserDao{publicdoublegetBalance(int user_id);//通过用户编号获取相应的余额publicvoidupdateBalance(int user_id,double price);//获取价格并修改用户相应的余额}
packagecn.edu.springdemo.transactionDemo.dao;publicinterfaceBookDao{publicintgetAmount(int book_id);//通过书本编号获取相应书本的数量publicdoublegetPrice(int book_id);//通过书本编号获取相应书本的价格publicvoidupdateAmount(int book_id,int amount);//获取购买数量并修改相应书本的数量}

创建接口对应的实现类:

packagecn.edu.springdemo.transactionDemo.dao;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.jdbc.core.JdbcTemplate;importorg.springframework.stereotype.Repository;@Repository("userDao")publicclassUserDaoImplimplementsUserDao{@AutowiredprivateJdbcTemplate jdbcTemplate;//通过JdbcTemplate操作数据库@OverridepublicdoublegetBalance(int user_id){String sql ="SELECT `balance` FROM `user` WHERE `id`=?;";return jdbcTemplate.queryForObject(sql,Double.class,user_id);}@OverridepublicvoidupdateBalance(int user_id,double price){if(getBalance(user_id)< price){thrownewRuntimeException("余额不足");//抛出异常}String sql ="UPDATE `user` SET `balance`=`balance`-? WHERE `id`=?;";
        jdbcTemplate.update(sql,price,user_id);}}
packagecn.edu.springdemo.transactionDemo.dao;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.jdbc.core.JdbcTemplate;importorg.springframework.stereotype.Repository;@Repository("bookDao")publicclassBookDaoImplimplementsBookDao{@AutowiredprivateJdbcTemplate jdbcTemplate;@OverridepublicintgetAmount(int book_id){String sql ="SELECT `amount` FROM `book` WHERE `id`=?;";return jdbcTemplate.queryForObject(sql,Integer.class,book_id);}@OverridepublicdoublegetPrice(int book_id){String sql ="SELECT `price` FROM `book` WHERE `id`=?;";return jdbcTemplate.queryForObject(sql,Double.class,book_id);}@OverridepublicvoidupdateAmount(int book_id,int amount){if(getAmount(book_id)< amount){thrownewRuntimeException("数量不足");}String sql ="UPDATE `book` SET `amount`=`amount`-? WHERE `id`=?;";
        jdbcTemplate.update(sql,amount,book_id);}}

再在 service 层创建一个 OrderService 接口,声明一个购买的方法:

packagecn.edu.springdemo.transactionDemo.service;publicinterfaceOrderService{publicvoidorder(int user_id,int book_id,int amount);//购买(用户id、书本id、购买数量)}

创建该接口对应的实现类:

packagecn.edu.springdemo.transactionDemo.service;importcn.edu.springdemo.transactionDemo.dao.BookDao;importcn.edu.springdemo.transactionDemo.dao.UserDao;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;@Service("orderService")publicclassOrderServiceImplimplementsOrderService{@AutowiredprivateBookDao bookDao;@AutowiredprivateUserDao userDao;@Transactional@Overridepublicvoidorder(int user_id,int book_id,int amount){//获取书本价格double price = bookDao.getPrice(book_id);//获取书本总价格double sum = price*amount;//购买//修改余额
        userDao.updateBalance(user_id,sum);//修改数量
        bookDao.updateAmount(book_id,amount);}}

然后,操作数据库。在上一章基础下,xml 配置再添加以下内容:

<?xml version="1.0" encoding="UTF-8"?><beansxmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 配置事务管理器 --><beanid="dataSourceTransactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!-- 配置dataSource --><propertyname="dataSource"ref="dataSource"></property></bean><!-- 开启事务注解 --><tx:annotation-driventransaction-manager="dataSourceTransactionManager"/></beans>

最后,测试结果:

packagecn.edu.springdemo.test;importcn.edu.springdemo.transactionDemo.service.OrderService;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclassTransactionTest{publicstaticvoidmain(String[] args){ApplicationContext applicationContext =newClassPathXmlApplicationContext("jdbc.xml");OrderService orderService =(OrderService) applicationContext.getBean("orderService");
        orderService.order(10101,20230612,2);//用户购买两本书,相应处理}}

执行前,结果如图:
在这里插入图片描述
在这里插入图片描述

执行后,结果如图:
在这里插入图片描述
在这里插入图片描述

异常测试,结果如图:
在这里插入图片描述

标签: Spring 事务

本文转载自: https://blog.csdn.net/qq_56886142/article/details/131117180
版权归原作者 啊Q老师 所有, 如有侵权,请联系我们删除。

“Spring:事务”的评论:

还没有评论