事务的隔离级别,回滚,只读,过期

当同一个应用程序或者不同应用程序中的多个事务在同一个数据集上并发执行时,可能会出现许多意外的问题。

并发事务所导致的问题可以分为下面三种类型:

-脏读

-不可重复读

-幻读

看代码:

db.properties

jdbc.user=root
jdbc.password=logan123
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/spring jdbc.initPoolSize=5
jdbc.maxPoolSize=10

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"> <context:component-scan base-package="logan.study.spring.tx"></context:component-scan> <!-- 导入资源文件 -->
<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> <!-- 配置Spring的JDBCTemplate -->
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean> <!-- 配置NamedParameterJdbcTemplate,该对象可以使用具名参数,其没有无参的构造器,所以必须为其构造器指定参数 -->
<bean id="namedParameterJdbcTemplate"
class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"></constructor-arg>
</bean> <!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean> <!-- 启用事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
package logan.study.spring.tx;

public interface BookShopDao {
//根据书号获取书的单价
public int findBookPriceIsbn(String isbn); //更新书的库存,使书号对应的库存-1
public void updateBookStock(String isbn); public void updateUserAccount(String username,int price); }
package logan.study.spring.tx;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository; @Repository("bookShopDao")
public class BookShopDaoImpl implements BookShopDao { @Autowired
private JdbcTemplate jdbcTemplate; @Override
public int findBookPriceIsbn(String isbn) {
// TODO Auto-generated method stub
String sql = "SELECT price FROM book WHERE isbn=?";
return jdbcTemplate.queryForObject(sql, Integer.class, isbn);
} @Override
public void updateBookStock(String isbn) {
// TODO Auto-generated method stub
//检查书的库存是否足够,若不够,则抛出异常
String sql2 = "SELECT stock FROM book_stock WHERE isbn = ?";
int stock = jdbcTemplate.queryForObject(sql2, Integer.class, isbn);
if(stock == 0){
throw new BookStockException("库存不足!");
}
String sql = "UPDATE book_stock SET stock = stock -1 WHERE isbn = ?";
jdbcTemplate.update(sql, isbn); } @Override
public void updateUserAccount(String username, int price) {
// TODO Auto-generated method stub
//检查书的库存是否足够,若不够,则抛出异常
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); } }
package logan.study.spring.tx;

public interface BookShopService {

    public void purchase(String username, String isbn);

}
package logan.study.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
@Override
public void purchase(String username, String isbn) {
// TODO Auto-generated method stub
//1.获取书的单价
int price = bookShopDao.findBookPriceIsbn(isbn);
//2.更新书的库存
bookShopDao.updateBookStock(isbn);
//3.更新用户余额
bookShopDao.updateUserAccount(username, price); } }
package logan.study.spring.tx;

import java.util.List;

public interface Cashier {
public void checkout(String username,List<String> isbns); }
package logan.study.spring.tx;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service("cashier")
public class CashierImpl implements Cashier{ @Autowired
private BookShopService bookShopService; /**
* 使用propagation指定事务的传播行为,即当前的事务方法被另外一个事务方法调用时
* 如何使用事务,默认取值为REQUIRED,即使用调用方法的事务
* REQUIRES_NEW事务自己的事务,调用事务方法的事务被挂起
* 使用isolation指定事务的隔离级别,最常用取值为READ_COMMITTED
* 默认情况下,Spring的声明式事务对所有的运行时异常进行回滚,也可以通过对应的属性进行设置
* 使用readonly 指定事务为只读,表示这个事务只读取数据单不更新数据,
* 这样可以帮助数据库引擎优化事务。若真的是一个只读数据库值的方法,应该设置readOnly=true
* 使用timeout指定强制回滚之前事务可以占用的时间。
*/
@Transactional(propagation=Propagation.REQUIRES_NEW,
isolation=Isolation.READ_COMMITTED,
noRollbackFor={UserAccountException.class})
@Override
public void checkout(String username, List<String> isbns) {
// TODO Auto-generated method stub
for(String isbn:isbns){
bookShopService.purchase(username, isbn);
} } }

当同一个应用程序或者不同应用程序中的多个事务在同一 个数据集上并发执行时,可能会出现许多意外的问题
并发事务所导致的问题可以分为下面三种类型:

-脏读:对于两个事物T1,T2,T1读取了已经被T2更新但还没有被 提交的字段.之后,若T2回滚,T1读取的内容就是临时且无效的.
-不可重复读:对于两个事物T1,T2,T1读取了一个字段,然后T2更 新了该字段.之后,T1再次读取同一个字段,值就不同了.

-幻读:对于两个事物T1,T2,T1从一个表中读取了一个字段,然后 T2在该表中插入了一些新的行.之后,如果T1再次读取同一个表, 就会多出几行.

Spring入门第二十九课的更多相关文章

  1. Spring入门第二十八课

    事务的传播行为 当事务方法被另一个事务方法调用时,必须指定事务应该如何传播,例如:方法可能继续在现有事务中运行,也可能开启一个新的事务,并在自己的事务中运行. 事务的传播行为可以由传播属性指定.Spr ...

  2. Spring入门第二十六课

    Spring中的事务管理 事务简介 事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性. 事务就是一系列的动作,他们被当做一个单独的工作单元,这些动作要么全部完成,要么全部不起 ...

  3. Spring入门第二十五课

    使用具名参数 直接看代码: db.properties jdbc.user=root jdbc.password=logan123 jdbc.driverClass=com.mysql.jdbc.Dr ...

  4. Spring入门第二十四课

    Spring对JDBC的支持 直接看代码: db.properties jdbc.user=root jdbc.password=logan123 jdbc.driverClass=com.mysql ...

  5. Spring入门第二十二课

    重用切面表达式 我们有的时候在切面里面有多个函数,大部分函数的切入点都是一样的,所以我们可以声明切入点表达式,来重用. package logan.study.aop.impl; public int ...

  6. NeHe OpenGL教程 第二十九课:Blt函数

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  7. python第二十九课——文件读写(复制文件)

    自定义函数:实现文件复制操作有形参(2个) 没有返回值相似版(不用) def copyFile(src,dest): #1.打开两个文件:1个关联读操作,1个关联写操作 fr=open(src,'rb ...

  8. python第二十九课——文件读写(读取读取中文字符)

    演示:读取中文字符 结论: 1).如果不设置encoding,默认使用gbk进行编解码 2).如果编码和解码不一致,最终导致报错,但是一旦设置了errors='ingore',那么就不会报错,而采取乱 ...

  9. Spring入门第二十课

    返回通知,异常通知,环绕通知 看代码: package logan.study.aop.impl; public interface ArithmeticCalculator { int add(in ...

随机推荐

  1. 剑指offer——树中两个节点的最低公共祖先

    代码来源与<剑指offer> 得到从根节点开始到输入的两个结点的两条,需要遍历两次树,每遍历一次的时间复杂度是O(n),得到的两条路径的长度在最差情况时是O(n),通常情况下两条路径的长度 ...

  2. J2EE 领域的一些技术框架结构图

    J2EE 领域的一些技术框架结构图       阿里百川,开启移动应用开发的新篇章 1.Spring 架构图 Spring 是一个开源 框架,是为了解决企业应用程序开发复杂性而创建的.框架的主要优势之 ...

  3. maven pom filter 导致的问题记录

    Maven提供了一个很不错的功能 Resource Filter, 可以将按不同环境的进行变量赋值, 比如数据库链接, redis, 日志输出位置等等.. 具体的filter如何使用我这里不做介绍, ...

  4. Echarts 地图(map)插件之 省份的颜色自定义

    ECharts,缩写来自Enterprise Charts,商业级数据图表,一个纯Javascript的图表库,可以流畅的运行在PC和移动设备上,兼容当前绝大部分浏览器(IE6/7/8/9/10/11 ...

  5. 给GridView删除列添加删除提示

         首先设置CommandField,把ShowEditButton.ShowDeleteButton属性都设置为true,也可以只设置ShowDeleteButton属性,那样下面的代码你要修 ...

  6. jQuery与javascript库

    [jquery-javascript库] 为了简化javascript的开发,诞生了javascript程序库,他封装了很多预定的对象和实用函数.下面是几种流行的javascript程序库:proto ...

  7. python 正则表达式(二)

    下面列举了Python3的所有符号用法,别背,千万别背,用到时来查就行. 字符 含义 . 表示匹配除了换行符外的任何字符注:通过设置 re.DOTALL 标志可以使 . 匹配任何字符(包含换行符) | ...

  8. Hibernate学习---第十三节:hibernate过滤器和拦截器的实现

    一.hibernate 过滤器 1.在持久化映射文件中配置过滤器,代码如下: <?xml version="1.0"?> <!DOCTYPE hibernate- ...

  9. 百度编辑器UEditor配置toolbars工具条功能按钮

    两种方式: 1.代码中定义 <script id="container" name="content" type="text/plain&quo ...

  10. BEC listen and translation exercise 40

    However, recently there's been more and more interest in the development of ostrich farming in other ...