博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用

内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系。

本人互联网技术爱好者,互联网技术发烧友

微博:伊直都在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中事物管理的更多相关文章

  1. [原创]java WEB学习笔记95:Hibernate 目录

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  2. [原创]java WEB学习笔记75:Struts2 学习之路-- 总结 和 目录

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  3. [原创]java WEB学习笔记66:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) 使用 paramsPrepareParamsStack 重构代码 ,PrepareInterceptor拦截器,paramsPrepareParamsStack 拦截器栈

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  4. Spring框架学习笔记(5)——Spring Boot创建与使用

    Spring Boot可以更为方便地搭建一个Web系统,之后服务器上部署也较为方便 创建Spring boot项目 1. 使用IDEA创建项目 2. 修改groupid和artifact 3. 一路n ...

  5. Spring实战第四章学习笔记————面向切面的Spring

    Spring实战第四章学习笔记----面向切面的Spring 什么是面向切面的编程 我们把影响应用多处的功能描述为横切关注点.比如安全就是一个横切关注点,应用中许多方法都会涉及安全规则.而切面可以帮我 ...

  6. Spring框架学习笔记(8)——spring boot+mybatis plus+mysql项目环境搭建

    之前写的那篇Spring框架学习笔记(5)--Spring Boot创建与使用,发现有多小细节没有提及,,正好现在又学习了mybatis plus这款框架,打算重新整理一遍,并将细节说清楚 1.通过I ...

  7. 五大 JAVA Web 框架的优缺点对比,Spring MVC 领先

    毫无疑问,Java 是当今世界上最重要的编程语言之一.js 框架给程序员提供了 一个可以构建程序的坚实基础.它包括定义的类和功能,用于硬件设备管理,与系统软件交互并处理输入,让开发人员变得更轻松.Ja ...

  8. 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 ...

  9. 学习笔记:CentOS7学习之二十:shell脚本的基础

    目录 学习笔记:CentOS7学习之二十:shell脚本的基础 20.1 shell 基本语法 20.1.1 什么是shell? 20.1.2 编程语言分类 20.1.3 什么是shell脚本 20. ...

  10. 学习笔记:CentOS7学习之十九:Linux网络管理技术

    目录 学习笔记:CentOS7学习之十九:Linux网络管理技术 本文用于记录学习体会.心得,兼做笔记使用,方便以后复习总结.内容基本完全参考学神教育教材,图片大多取材自学神教育资料,在此非常感谢MK ...

随机推荐

  1. 【bzoj1499】瑰丽华尔兹

    这名字听起来实在有点耳熟..? 好吧去年暑假就应该过的题...切了 先注意到,天使施魔法的次数不限:我们可以使得某个时刻在特定方向移动一段距离(最长的长度为那个时间段)然后怎么来考虑这个DP: T,X ...

  2. Hbase0.96 MVCC Lock 知识梳理

    HBASE0.96 MVCC 写入的时候 每个Region包含一个Memstore,维护一个MultiVersionConsistencyControl对象 w = mvcc.beginMemstor ...

  3. XVI Open Cup named after E.V. Pankratiev. GP of Eurasia

    A. Nanoassembly 首先用叉积判断是否在指定向量右侧,然后解出法线与给定直线的交点,再关于交点对称即可. #include<bits/stdc++.h> using names ...

  4. 2014亚马逊在线笔试题目及解决方案(MMChess问题)

    整体思路:关键是需要知道当前Steps数组中的全排列即可,而且需要不重复的全排列.即关键在于非递归的全排列实现即可~ 其实直接利用STL中的next_permutation算法的,这里我又自己实现了一 ...

  5. Codeforces Round #107 (Div. 2)

    D题 并查集+组合 #include <iostream> #include <cstdio> #include <cstring> using namespace ...

  6. 利用轮播原理结合hammer.js实现简洁的滑屏功能

    最近有个任务,做一个非常小的h5的应用,只有2屏,需要做横向的全屏滑动切换和一些简单的动画效果,之前做这种东西用的是fullpage.js和jquery,性能不是很好,于是就想自己动手弄一个简单的东西 ...

  7. java分享第六天(冒泡排序)

    冒泡排序 基本思想: 在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒.即:每当两相邻的数比较后发现它们 的排序与排序要求 ...

  8. c# 反射事件

    被反射类中: public delegate void CompeletedHandler(); public static event CompeletedHandler AnalysisCompe ...

  9. 小米网站登录源码C#版

    一步一步做,肯定能成功 HttpHelper类请从网络上搜索 string postData = getPostData(); HttpHelper ht = new HttpHelper(); Ht ...

  10. WPF整理-XAML访问静态属性

    "XAML provides an easy way to set values of properties—type converters and the extended propert ...