[原创]java WEB学习笔记109:Spring学习---spring中事物管理
博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用
内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系。
本人互联网技术爱好者,互联网技术发烧友
微博:伊直都在0221
QQ:951226918
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1.事务简介
1)事务管理是企业级应用程序开发中必不可少的技术, 用来确保数据的完整性和一致性.
2)事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用
3)事务的四个关键属性(ACID)
① 原子性(atomicity): 事务是一个原子操作, 由一系列动作组成. 事务的原子性确保动作要么全部完成要么完全不起作用.
② 一致性(consistency): 一旦所有事务动作完成, 事务就被提交. 数据和资源就处于一种满足业务规则的一致性状态中.
③ 隔离性(isolation): 可能有许多事务会同时处理相同的数据, 因此每个事物都应该与其他事务隔离开来, 防止数据损坏.
④ 持久性(durability): 一旦事务完成, 无论发生什么系统错误, 它的结果都不应该受到影响. 通常情况下, 事务的结果被写到持久化存储器中.
2.在JDBC中事物的处理
3.spring 中的事物处理
1)作为企业级应用程序框架, Spring 在不同的事务管理 API 之上定义了一个抽象层. 而应用程序开发人员不必了解底层的事务管理 API, 就可以使用 Spring 的事务管理机制.
2)Spring 既支持编程式事务管理, 也支持声明式的事务管理.
3)编程式事务管理: 将事务管理代码嵌入到业务方法中来控制事务的提交和回滚. 在编程式管理事务时, 必须在每个事务操作中包含额外的事务管理代码.
4)声明式事务管理: 大多数情况下比编程式事务管理更好用. 它将事务管理代码从业务方法中分离出来, 以声明的方式来实现事务管理. 事务管理作为一种横切关注点, 可以通过 AOP 方法模块化. Spring 通过 Spring AOP 框架支持声明式事务管理.
5)Spring 从不同的事务管理 API 中抽象了一整套的事务机制. 开发人员不必了解底层的事务 API, 就可以利用这些事务机制. 有了这些事务机制, 事务管理代码就能独立于特定的事务技术了.
6)spring 的核心事务管理抽象是 org.springframework.transaction Interface PlatformTransactionManager 它为事务管理封装了一组独立于技术的方法. 无论使用 Spring 的哪种事务管理策略(编程式或声明式), 事务管理器都是必须的.
4.Spring 中的事务管理器的不同实现
5.实例需求
1)类图
2)代码结构
3)具体代码
- package com.jason.spring.tx;
- public interface BookShopDao {
- //根据书号获取书的单价
- public int findBookPirceByIsbn(String isbn);
- //更新书的库存,使对应的书号 - 1
- public void updateBookStock(String isbn);
- //更新用户的账户余额:是username 的balance - price
- public void updateUserAccount(String username, int price);
- }
BookShopDao
- package com.jason.spring.tx;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.jdbc.core.JdbcTemplate;
- import org.springframework.stereotype.Repository;
- @Repository("bookStockImpl")
- public class BookShopImpl implements BookShopDao{
- @Autowired
- private JdbcTemplate jdbcTemplate;
- @Override
- public int findBookPirceByIsbn(String isbn) {
- String sql = "SELECT price FROM book WHERE isbn = ?";
- return jdbcTemplate.queryForObject(sql, Integer.class, isbn);
- }
- @Override
- public void updateBookStock(String isbn) {
- //检查书的库存是否足够,若不够,则抛出异常
- String sql2 = "SELECT stock FROM book_stock WHERE isbn = ?";
- int stock = jdbcTemplate.queryForObject(sql2, Integer.class, isbn);
- if(stock == 0){
- throw new BookStockExceprtion("库存不足!!!");
- }
- String sql = "UPDATE book_stock SET stock = stock -1 WHERE isbn = ?";
- jdbcTemplate.update(sql, isbn);
- }
- @Override
- public void updateUserAccount(String username, int price) {
- //验证余额是否足够,若不足,则抛出异常
- String sql2 = "SELECT balance FROM account WHERE username = ?";
- int balance = jdbcTemplate.queryForObject(sql2, Integer.class, username);
- if(balance < price){
- throw new UserAccountException("余额不足!!!");
- }
- String sql = "UPDATE account SET balance = balance - ? WHERE username = ?";
- jdbcTemplate.update(sql, price, username);
- }
- }
BookShopImpl
- package com.jason.spring.tx;
- public interface BookShopService {
- public void purchase(String username, String isbn);
- }
BookShopService
- package com.jason.spring.tx;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- @Service("bookShopService")
- public class BookShopServiceImpl implements BookShopService{
- @Autowired
- private BookShopDao bookShopDao;
- @Transactional
- public void purchase(String username, String isbn) {
- //1.读取书的单价
- int price = bookShopDao.findBookPirceByIsbn(isbn);
- //2.更新书的库存
- bookShopDao.updateBookStock(isbn);
- //3.更新用户的余额
- bookShopDao.updateUserAccount(username, price);
- }
- }
BookShopServiceImpl
- package com.jason.spring.tx;
- public class BookStockExceprtion extends RuntimeException{
- public BookStockExceprtion() {
- super();
- // TODO Auto-generated constructor stub
- }
- public BookStockExceprtion(String message, Throwable cause,
- boolean enableSuppression, boolean writableStackTrace) {
- super(message, cause, enableSuppression, writableStackTrace);
- // TODO Auto-generated constructor stub
- }
- public BookStockExceprtion(String message, Throwable cause) {
- super(message, cause);
- // TODO Auto-generated constructor stub
- }
- public BookStockExceprtion(String message) {
- super(message);
- // TODO Auto-generated constructor stub
- }
- public BookStockExceprtion(Throwable cause) {
- super(cause);
- // TODO Auto-generated constructor stub
- }
- }
BookStockExceprtion
- package com.jason.spring.tx;
- public class UserAccountException extends RuntimeException{
- public UserAccountException() {
- super();
- // TODO Auto-generated constructor stub
- }
- public UserAccountException(String message, Throwable cause,
- boolean enableSuppression, boolean writableStackTrace) {
- super(message, cause, enableSuppression, writableStackTrace);
- // TODO Auto-generated constructor stub
- }
- public UserAccountException(String message, Throwable cause) {
- super(message, cause);
- // TODO Auto-generated constructor stub
- }
- public UserAccountException(String message) {
- super(message);
- // TODO Auto-generated constructor stub
- }
- public UserAccountException(Throwable cause) {
- super(cause);
- // TODO Auto-generated constructor stub
- }
- }
UserAccountException
- package com.jason.spring.tx;
- import static org.junit.Assert.*;
- import org.junit.Test;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class BookStockImplTest {
- private ApplicationContext ctx = null;
- private BookShopDao bookShopDao = null;
- private BookShopService bookShopService = null;
- {
- ctx = new ClassPathXmlApplicationContext("application.xml");
- bookShopDao = ctx.getBean(BookShopDao.class);
- bookShopService = ctx.getBean(BookShopService.class);
- }
- @Test
- public void testFindBookPirceByIsbn() {
- System.out.println(bookShopDao.findBookPirceByIsbn("1001"));
- }
- @Test
- public void testUpdateBookStock() {
- bookShopDao.updateBookStock("1001");
- }
- @Test
- public void testUpdateUserAccount() {
- bookShopDao.updateUserAccount("tom", 200);
- }
- @Test
- public void testBookShopService(){
- bookShopService.purchase("jason", "1001");
- }
- }
BookStockImplTest
6.实现声明式事物的步骤
1)在xml文件中,配置管理事物,启用管理事物
- <!-- 导入资源文件 -->
- <context:property-placeholder location="classpath:db.properties"/>
- <!-- 配置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>
- <!-- 配置事物管理器:针对数据源 -->
- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource"></property>
- </bean>
- <!-- 启用事物注解:需要导入tx命名空间 -->
- <tx:annotation-driven transaction-manager="transactionManager"/>
2)在对应的方法前加入@Transactional 注解
- @Transactional
- public void purchase(String username, String isbn) {
- //1.读取书的单价
- int price = bookShopDao.findBookPirceByIsbn(isbn);
- //2.更新书的库存
- bookShopDao.updateBookStock(isbn);
- //3.更新用户的余额
- bookShopDao.updateUserAccount(username, price);
- }
7.事物的其他属性
1)事务传播属性:当事务方法被另一个事务方法调用时, 必须指定事务应该如何传播. 例如: 方法可能继续在现有事务中运行, 也可能开启一个新事务, 并在自己的事务中运行. 事务的传播行为可以由传播属性指定. Spring 定义了 7 种类传播行为.
2)@Transactional(propagation=Propagation.REQUIRED) 使用propagation 指定事物传播行为,即当前的事物方法被另外一个事物调用时,如何使用事物。默认值为 REQUIRED
3)isolation 指定事物的隔离级别 ,最常见值为READ_COMMITTED
4)默认情况下 Spring 的声明式事物对所有的运行时异常进行回滚,也可以通过对应的属性设置.通常取默认值
① 事务的回滚规则可以通过 @Transactional 注解的 rollbackFor 和 noRollbackFor 属性来定义. 这两个属性被声明为 Class[] 类型的, 因此可以为这两个属性指定多个异常类
rollbackFor: 遇到时必须进行回滚
5)使用readOnly 指定事物为只读.表示这个事务只读取数据但不更新数据, 这样可以帮助数据库引擎优化事务.若真的是一个只读取数据库值的方法,应设置readOnly=true
6)使用timeout 指定强制混滚之前事物可以占用的时间 ,单位 秒
① 由于事务可以在行和表上获得锁, 因此长事务会占用资源, 并对整体性能产生影响.
② 如果一个事物只读取数据但不做修改, 数据库引擎可以对这个事务进行优化.
③超时事务属性: 事务在强制回滚之前可以保持多久. 这样可以防止长期运行的事务占用资源.
- @Transactional(propagation=Propagation.REQUIRED ,
- isolation=Isolation.READ_COMMITTED,
- noRollbackFor={UserAccountException.class},
- readOnly=false,
- timeout=1)
- public void purchase(String username, String isbn) {
}
[原创]java WEB学习笔记109:Spring学习---spring中事物管理的更多相关文章
- [原创]java WEB学习笔记95:Hibernate 目录
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- [原创]java WEB学习笔记75:Struts2 学习之路-- 总结 和 目录
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- [原创]java WEB学习笔记66:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) 使用 paramsPrepareParamsStack 重构代码 ,PrepareInterceptor拦截器,paramsPrepareParamsStack 拦截器栈
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- Spring框架学习笔记(5)——Spring Boot创建与使用
Spring Boot可以更为方便地搭建一个Web系统,之后服务器上部署也较为方便 创建Spring boot项目 1. 使用IDEA创建项目 2. 修改groupid和artifact 3. 一路n ...
- Spring实战第四章学习笔记————面向切面的Spring
Spring实战第四章学习笔记----面向切面的Spring 什么是面向切面的编程 我们把影响应用多处的功能描述为横切关注点.比如安全就是一个横切关注点,应用中许多方法都会涉及安全规则.而切面可以帮我 ...
- Spring框架学习笔记(8)——spring boot+mybatis plus+mysql项目环境搭建
之前写的那篇Spring框架学习笔记(5)--Spring Boot创建与使用,发现有多小细节没有提及,,正好现在又学习了mybatis plus这款框架,打算重新整理一遍,并将细节说清楚 1.通过I ...
- 五大 JAVA Web 框架的优缺点对比,Spring MVC 领先
毫无疑问,Java 是当今世界上最重要的编程语言之一.js 框架给程序员提供了 一个可以构建程序的坚实基础.它包括定义的类和功能,用于硬件设备管理,与系统软件交互并处理输入,让开发人员变得更轻松.Ja ...
- ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则
ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...
- 学习笔记:CentOS7学习之二十:shell脚本的基础
目录 学习笔记:CentOS7学习之二十:shell脚本的基础 20.1 shell 基本语法 20.1.1 什么是shell? 20.1.2 编程语言分类 20.1.3 什么是shell脚本 20. ...
- 学习笔记:CentOS7学习之十九:Linux网络管理技术
目录 学习笔记:CentOS7学习之十九:Linux网络管理技术 本文用于记录学习体会.心得,兼做笔记使用,方便以后复习总结.内容基本完全参考学神教育教材,图片大多取材自学神教育资料,在此非常感谢MK ...
随机推荐
- TodoMVC中的Backbone+MarionetteJS+RequireJS例子源码分析之一
Marionette牵线木偶,Backbone是脊骨的意思,Marionette是基于Backbone做扩展库,可以理解为把脊骨骨架绑线扯着变成牵线木偶动起来哈哈,使backbone更易使用呵呵! 构 ...
- Only Link: What's the difference between dynamic dispatch and dynamic binding
http://stackoverflow.com/questions/20187587/what-is-the-difference-between-dynamic-dispatch-and-late ...
- phpunit学习 3:
16:17 2015/12/11phpunit学习 3:单元测试的大概步骤是:编写待测试类,编写测试用例类,编写测试类,测试.1.如果你有多个类,多个测试类的test类,那么可以编写一个AllTest ...
- java 输入年月,获取日历表
/* 做日历作业: 输入一个时间如: 2016-11 就显示2016年11月的日历显示 */ import java.util.*; class calendar { public static vo ...
- Bash On Win10 (WSL) 安装 Odoo 开发环境
前段时间微软发布了Bash On Win10,虽然目前还是Beta阶段,但是一想到再也不用折腾虚拟机上跑odoo了,就忍不住手痒,尝试在WSL上安装了一下odoo,结果比较惊喜,感觉可以抛弃Vitru ...
- 获取移除指定Url参数(原创)
/// <summary> /// 移除指定的Url参数 /// 来自:http://www.cnblogs.com/cielwater /// </summary> /// ...
- java按值传递理解
Java没有引用传递只有按值传递,没有引用传递只有按值传递,值传递. 通过下面代码解释: public class Test { public static void main(String[] ar ...
- 读取java目录中相同目录、相同名称的文件
使用ClassLoader的getResources方法(注意,不是getResource,少了s),可获得指定文件的包含jar包名称的多个路径值,然后依次读取文件即可. 使用class,只能通过ge ...
- Tomcat 随机挂掉
最近遇到一些诡异的事情,1Apache + 4Tomcat的系统中,每天偶尔会发现其中的一台或几台Tomcat宕机了. 今天特别频繁,宕了有6次之多. 环境: Windows Server 20 ...
- 过滤关键字防止XSS攻击
public static string ClearXSS(string str) { string returnValue = str; if (string.IsNullOrEmpty(retur ...