Spring 声明式事务
事务的特性/概念
- 原子性(atomicity):“原子”的本意是“不可再分”,事务的原子性表现为一个事务中涉及到的多个操作在逻辑上缺一不可。事务的原子性要求事务中的所有操作要么都执行,要么都不执行。
- 一致性(consistency):“一致”指的是数据的一致,具体是指:所有数据都处于满足业务规则的一致性状态。一致性原则要求:一个事务中不管涉及到多少个操作,都必须保证事务执行之前数据是正确的,事务执行之后数据仍然是正确的。如果一个事务在执行的过程中,其中某一个或某几个操作失败了,则必须将其他所有操作撤销,将数据恢复到事务执行之前的状态,这就是回滚。
- 隔离性(isolation):在应用程序实际运行过程中,事务往往是并发执行的,所以很有可能有许多事务同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。隔离性原则要求多个事务在并发执行过程中不会互相干扰。
- 持久性(durability):持久性原则要求事务执行完成后,对数据的修改永久的保存下来,不会因各种系统错误或其他意外情况而受到影响。通常情况下,事务对数据的修改应该被写入到持久化存储器中。
jar包
<!--1、配置连接池 -->
<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/tx"></property>
</bean>
<!--2、数据库的增删改查 JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="comboPooledDataSource"></property>
</bean>
<!--配置事务切面;控制住连接池 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="comboPooledDataSource"></property>
</bean> <!--开启基于注解的事务功能;依赖tx名称空间
transaction-manager:指定事务管理器是哪个
-->
<tx:annotation-driven/>
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository; /**
* [1]根据isbn的值查询书的价格,
public int getPrice(String isbn);
[2]根据isbn的值减少书的库存,假设每次都只买1本书,
public void updateStock(String isbn);
[3]根据用户名减少用户账户中的余额,减少的额度就是书的价格
public void updateBalance(int price,String user);
* @author lfy
*
*/
@Repository
public class BookDao { @Autowired
JdbcTemplate jdbcTemplate; /**
* [1]根据isbn的值查询书的价格,
* public int getPrice(String isbn);
* 操作:book
*/
public int getPrice(String isbn){
String sql = "select price from book where isbn=?";
Integer price = jdbcTemplate.queryForObject(sql, Integer.class, isbn);
return price;
}; /**
* [2]根据isbn的值减少书的库存,假设每次都只买1本书,
* public void updateStock(String isbn);
* 操作:book_stock
*/
public void updateStock(String isbn){
String sql = "UPDATE book_stock SET stock=stock-1 WHERE isbn=?";
jdbcTemplate.update(sql, isbn);
} /**
* [3]根据用户名减少用户账户中的余额,减少的额度就是书的价格
* public void updateBalance(int price,String user);
* 给用户减余额;account
* String user:要减余额的用户名
* int price:要减掉多少(减少的额度就是书的价格)
*/
public void updateBalance(int price,String user){
String sql = "update account set balance = balance-? where username=?";
jdbcTemplate.update(sql, price,user); } public void updatePrice(String isbn){
String sql = "update book set price = 999 WHERE isbn=?";
jdbcTemplate.update(sql, isbn);
}
}
事务注解主要添加在Service层,通过Aop来实现事务操作:
import java.io.FileInputStream;
import java.io.FileNotFoundException; 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; import com.atguigu.dao.BookDao; @Service
public class BookService { @Autowired
BookDao bookDao; @Transactional(noRollbackFor=ArithmeticException.class,
timeout=3,propagation=Propagation.REQUIRES_NEW)
public void checkout(String username,String isbn){
//0、查出图书价格
int price = bookDao.getPrice(isbn);
//1、减用户余额
bookDao.updateBalance(price, username);
//2、减图书的库存
bookDao.updateStock(isbn); //Thread.sleep(3000);
//new FileInputStream("D://ahahahah//aa.txt");
System.out.println("结账完成....");
} @Transactional(propagation=Propagation.REQUIRED,timeout=3)
public void updatePrice(String isbn){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
bookDao.updatePrice(isbn);
} }
Spring事务管理器
事务控制的属性:
propagation:事务的传播行为;我们可以通过控制指定大事务和小事务的关系;
传播(共用一个事务的情况下大事务的属性配置会传播给小事务)+行为(是否共用一个事务)。
- 脏读:同一事务期间,数据还没提交就给回滚了。
- 不可重复读:同一事务期间,多次读取数据内容不一样。
- 幻读:同一事务期间,多次读取数据,发现记录变少或者变多了。
本质上一个再读,一个在改;
数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别。SQL标准中规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。
①读未提交:READ UNCOMMITTED
允许Transaction01读取Transaction02未提交的修改。
②读已提交:READ COMMITTED
要求Transaction01只能读取Transaction02已提交的修改。
③可重复读:REPEATABLE READ
确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其它事务对这个字段进行更新。
④串行化:SERIALIZABLE
确保Transaction01可以多次从一个表中读取到相同的行,在Transaction01执行期间,禁止其它事务对这个表进行添加、更新、删除操作。可以避免任何并发问题,但性能十分低下。
⑤各个隔离级别解决并发问题的能力见下表
⑥各种数据库产品对事务隔离级别的支持程度
在Spring中指定事务隔离级别
注解
用@Transactional注解声明式地管理事务时可以在@Transactional的isolation属性中设置隔离级别
XML
在Spring 2.x事务通知中,可以在<tx:method>元素中指定隔离级别
触发事务回滚的异常
默认情况
捕获到RuntimeException或Error时回滚,而捕获到编译时异常不回滚。
设置途经
注解
@Transactional 注解
- rollbackFor属性:指定遇到时必须进行回滚的异常类型,可以为多个
- noRollbackFor属性:指定遇到时不回滚的异常类型,可以为多个
XML
在Spring 2.x事务通知中,可以在<tx:method>元素中指定回滚规则。如果有不止一种异常则用逗号分隔。
事务的超时和只读属性
简介
由于事务可以在行和表上获得锁,因此长事务会占用资源,并对整体性能产生影响。
如果一个事物只读取数据但不做修改,数据库引擎可以对这个事务进行优化。
超时事务属性:事务在强制回滚之前可以保持多久。这样可以防止长期运行的事务占用资源。
只读事务属性: 表示这个事务只读取数据但不更新数据, 这样可以帮助数据库引擎优化事务。
设置
注解
@Transaction注解
XML
在Spring 2.x事务通知中,超时和只读属性可以在<tx:method>元素中进行指定
举个比较完整的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"
xmlns:aop="http://www.springframework.org/schema/aop"
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.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <context:component-scan base-package="com.atguigu"></context:component-scan> <!--1、配置连接池 -->
<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/tx"></property>
</bean> <!--2、数据库的增删改查 JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="comboPooledDataSource"></property>
</bean> <!--3、配置事务切面;控制住连接池 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="comboPooledDataSource"></property>
</bean> <!--4、开启基于注解的事务功能;依赖tx名称空间
transaction-manager:指定事务管理器是哪个
-->
<!-- <tx:annotation-driven/> --> <!--基于xml的事务配置;需要aop和tx名称空间 -->
<!-- transactionManager事务切面 -->
<aop:config>
<!--指定事务管理器要切入哪些方法进行事务控制 -->
<aop:pointcut expression="execution(* com.soyoungboy.service.*.*(..))" id="txPoint"/>
<!-- aop:advisor:建议; pointcut-ref:使用指定的切入点表达式切入事务 -->
<aop:advisor advice-ref="myTxAdvice" pointcut-ref="txPoint"/>
</aop:config> <!-- 使用tx名称空间和配置(事务建议、事务属性、事务增强);事务方法怎么执行
id="myTxAdvice":随便起,别人要引用<aop:advisor advice-ref="myTxAdvice"
transaction-manager="transactionManager":指定配置哪个事务管理器
-->
<tx:advice id="myTxAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 指定事务方法:代表所有方法是事务方法 -->
<tx:method name="*"/>
<tx:method name="checkout" rollback-for="java.lang.Exception"/>
<tx:method name="updatePrice" propagation="REQUIRES_NEW"/>
<!--以get开头的,通过只读来进行优化-->
<tx:method name="get*" read-only="true"/>
</tx:attributes>
</tx:advice> <!-- 基于xml配置的事务控制更多一点 --> </beans>
Spring 声明式事务的更多相关文章
- spring声明式事务管理总结
事务配置 首先在/WEB-INF/applicationContext.xml添加以下内容: <!-- 配置事务管理器 --> <bean id="transactionM ...
- spring 声明式事务管理
简单理解事务: 比如你去ATM机取5000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉5000元钱:然后ATM出5000元钱.这两个步骤必须是要么都执行要么都不执行.如果银行卡扣除了5000块但 ...
- Spring声明式事务管理基于@Transactional注解
概述:我们已知道Spring声明式事务管理有两种常用的方式,一种是基于tx/aop命名空间的xml配置文件,另一种则是基于@Transactional 注解. 第一种方式我已在上文为大 ...
- Spring声明式事务管理基于tx/aop命名空间
目的:通过Spring AOP 实现Spring声明式事务管理; Spring支持编程式事务管理和声明式事务管理两种方式. 而声明式事务管理也有两种常用的方式,一种是基于tx/aop命名空间的xml配 ...
- Spring声明式事务配置管理方法
环境配置 项目使用SSH架构,现在要添加Spring事务管理功能,针对当前环境,只需要添加Spring 2.0 AOP类库即可.添加方法: 点击项目右键->Build Path->Add ...
- 161117、使用spring声明式事务抛出 identifier of an instance of
今天项目组有成员使用spring声明式事务出现下面异常,这里跟大家分享学习下. 异常信息: org.springframework.orm.hibernate3.HibernateSystemExce ...
- Spring声明式事务管理与配置详解
转载:http://www.cnblogs.com/hellojava/archive/2012/11/21/2780694.html 1.Spring声明式事务配置的五种方式 前段时间对Spring ...
- Spring声明式事务配置管理方法(转)
项目使用SSH架构,现在要添加Spring事务管理功能,针对当前环境,只需要添加Spring 2.0 AOP类库即可.添加方法: 点击项目右键->Build Path->Add libra ...
- Spring声明式事务的配置~~~
/*2011年8月28日 10:03:30 by Rush */ 环境配置 项目使用SSH架构,现在要添加Spring事务管理功能,针对当前环境,只需要添加Spring 2.0 AOP类库即可.添加 ...
- Spring 声明式事务,propagation属性列表及isolation(隔离级别)
Spring 声明式事务,propagation属性列表 TransactionDefinition接口中定义,共有7种选项可用: PROPAGATION_REQUIRED:支持当前事务,如果当前没有 ...
随机推荐
- tomcat server.xml各个端口的作用
<Server port="8005" shutdown="SHUTDOWN"> <!-- port:指定一个端口,这个端口负责监听关闭Tom ...
- 【学亮IT手记】angularJS+select2多选下拉框实例
永远保持对大部分知识的好奇心,学习从不枯燥,也没有被逼学习一说,乐此不疲才是该有的心态和境界!!! 引入相关js库: html部分代码: angularJS定义数据源变量:
- VSC软件快捷键
Shift + Alt + F 格式化 Ctrl+Shift+P, F1显示命令面板 Ctrl+P快速打开,进入File… Ctrl + Shift + N新窗口/实例 Ctrl + Shift + ...
- JS对象、基本类型和字面量的区别
字面值: var str1='this is a simple string'; var num1=1.45; var answer1=true; 基本类型: var str2=String('thi ...
- Failed to bind properties under 'spring.datasource' to javax.sql.DataSource
这是我的配置文件 # 国际化配置文件(包名.基础名) spring.messages.basename=i18n.login server.tomcat.uri-encoding=UTF- sprin ...
- 莫烦theano学习自修第九天【过拟合问题与正规化】
如下图所示(回归的过拟合问题):如果机器学习得到的回归为下图中的直线则是比较好的结果,但是如果进一步控制减少误差,导致机器学习到了下图中的曲线,则100%正确的学习了训练数据,看似较好,但是如果换成另 ...
- 多IP地址--笔记
多IP 地址特性使虚拟用户可以在一个load generator上运行且被识别为多个IP地址 1 虚拟IP是同一个generator上的多个IP,这种分配过程由controller自动来进行 2 对于 ...
- C#后台绑定select
- codeforces611C
New Year and Domino CodeForces - 611C 他们说:“每一年都像多米诺骨牌,一个接一个地倒下去”.但是,一年能够像多米诺骨牌那样放在网格中吗?我不这么认为. Zydsg ...
- django--orm关系字段(ForeignKey、OneToOneField、ManyToManyField)详解
django中的关系字段 1.ForeignKey字段,即外键字段,对应一对多的情况,列如:一本书对应一个出版社,一个出版社可对应多本书. 2.ManyToManyFiled字段,即多对多字段,对应数 ...