[原创]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 ...
随机推荐
- 编译原理-词法分析04-NFA & 代码实现
编译原理-词法分析04-NFA & 代码实现 0.术语 NFA 非确定性有穷自动机nondeterministic finite automation. ε-转换ε-transition 是无 ...
- java-Lambda表达式
浏览以下内容前,请点击并阅读 声明 Lambda表达式与匿名类的作用类似,当实现的接口仅有一个方法时,使用lambda表达式能够减少代码的使用量. //此处定义一个仅含有一个抽象方法的功能接口 int ...
- html上下结构(上部固定高度,下部平铺)
html页面上下结构: 上部固定,下部平铺 <div id="page_header"></div> <div id="page_conte ...
- XVI Open Cup named after E.V. Pankratiev. GP of SPB
A. Bubbles 枚举两个点,求出垂直平分线与$x$轴的交点,答案=交点数+1. 时间复杂度$O(n^2\log n)$. #include<cstdio> #include<a ...
- VR的世界里没有雾霾!暴风魔镜发布Matrix一体机
在2016年接近尾声的时候,暴风魔镜给VR行业带来一波暖流.12月20日,暴风魔镜宣布推出最新VR一体机--暴风魔镜"3K屏概念机"MATrix及VR眼镜S1两大产品. ...
- iOS tableview删除多余的空cell
self.tableview.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; 加一句这个,然后给tableview一个背景色, ...
- 谢欣伦 - OpenDev原创教程 - 设备查找类CxDeviceFind & CxDeviceMapFind
这是一个精练的设备查找类,类名.函数名和变量名均采用匈牙利命名法.小写的x代表我的姓氏首字母(谢欣伦),个人习惯而已,如有雷同,纯属巧合. CxDeviceFind的使用如下: void CUsbSc ...
- awk匹配
输出匹配funcno或type:awk 'funcno|type' 输出两次正则表达式匹配之间的行:awk '/funcno/, /type/' 删除所有的空行:awk NF 从第8行输出到第12行: ...
- 规范和封装jdbc程序代码
JDBC 部分方法引用工具类 package it.cast.jdbc; import java.sql.Connection; import java.sql.DriverManager; impo ...
- java classpath getResource getResourceAsStream
1.classpath 用于指定java运行时,jvm寻找class文件以及jar文件的存储目录.jvm依据classpath中出现的jar文件以及目录,依次寻找,直到找到指定class文件. 例:j ...