Spring学习六(事物管理)
参考链接
http://www.mamicode.com/info-detail-1248286.html
http://www.cnblogs.com/wangdaqian/archive/2017/06/01/6929843.html
http://www.cnblogs.com/fjdingsd/p/5632949.html
http://blog.csdn.net/bao19901210/article/details/41724355
http://blog.csdn.net/u011726984/article/details/45421151
Spring的事物管理分为两种,一种是编程式,一种是声明式。因为声明式基于AOP原理,不侵入代码。所以常用声明式。
根据这个图分析:
1 无论声明式还是编程式,transactionmanager必须加载,对应的不同形式的transactionmanager也不同,比如Hibernate, JDBC原生(DataSourceTransactionManager) Jta ,Spring只是提供一个manager的接口,具体的实现要具体的框架去加载,不同的事物详细配置请看上方链接。
2 常用申明式
3 编程式分为Transaction template 和PlatformTransactionManager 一般用前者。
4 声明式是基于AOP的非侵入式,所以常用,但是编程式有更佳控制。
重点:
spring事务特性
spring所有的事务管理策略类都继承自org.springframework.transaction.PlatformTransactionManager接口
其中TransactionDefinition接口定义以下特性:
事务隔离级别
隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了五个表示隔离级别的常量:
- TransactionDefinition.ISOLATION_DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED。
- TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。
- TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
- TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。
- TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
事务传播行为
所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了如下几个表示传播行为的常量:
- TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
- TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
- TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
- TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
- TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
- TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
- TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
事务超时
所谓事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒。
默认设置为底层事务系统的超时值,如果底层数据库事务系统没有设置超时值,那么就是none,没有超时限制。
事务只读属性
“只读事务”并不是一个强制选项,它只是一个“暗示”,提示数据库驱动程序和数据库系统,这个事务并不包含更改数据的操作,那么JDBC驱动程序和数据库就有可能根据这种情况对该事务进行一些特定的优化,比方说不安排相应的数据库锁,以减轻事务对数据库的压力,毕竟事务也是要消耗数据库的资源的。
但是你非要在“只读事务”里面修改数据,也并非不可以,只不过对于数据一致性的保护不像“读写事务”那样保险而已。
因此,“只读事务”仅仅是一个性能优化的推荐配置而已,并非强制你要这样做不可
声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。
代码如下
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.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd"> <!-- 配置配置文件 -->
<context:property-placeholder location="classpath:db.properties" /> <!-- 配置数据源文件 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="initialPoolSize" value="${jdbc.iniPoolSize}"></property>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
</bean> <!-- 两种编程式的事物管理 一种是 TransactionTemplate 一种是PlatformTransactionManager --> <!-- 配置template -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean> <!-- 配置带参template -->
<bean id="namedtemplate"
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> <!-- 编程式templete方法 -->
<bean id="transactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean> <bean id="accountDao" class="Test.AccountDao">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
<property name="transactionTemplate" ref="transactionTemplate"></property>
</bean> <!-- 声明式方法,因为是基于AOP方式,所以下面要配置AOP -->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<tx:attributes><!-- 可以在里面指定很多方法 这里我就只指定一个了 -->
<tx:method name="transactionMoney2" rollback-for="Exception"/><!--
可以在里面设置propagation,timeout,isolation,rollbackfor and no for 等等-->
</tx:attributes>
</tx:advice> <!-- 没有注释掉就是非注解声明式 模式
<aop:config>
<aop:pointcut expression="execution(* Test.AccountDao.*(..))" id="AccountPointCut" />
<aop:advisor advice-ref="txadvice" pointcut-ref="AccountPointCut" />
</aop:config>
--> <!-- 开启事务控制的注解回滚模式 @Transactional -->
<tx:annotation-driven transaction-manager="transactionManager"/> <context:component-scan base-package="Test"></context:component-scan>
</beans>
java测试代码如下
package Test; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate; public class AccountDao {
private JdbcTemplate jdbcTemplate;
private TransactionTemplate transactionTemplate; public TransactionTemplate getTransactionTemplate() {
return transactionTemplate;
} public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
} public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
} public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
} public int getCount(int id) {
// String sql ="SELECT count FROM account where id=?"; 不要用count
// 这是sql里面计算要用的 String sql = "SELECT count1 FROM account where id=?";
Integer count = jdbcTemplate.queryForObject(sql, Integer.class, id);
return count;
} public void addMoney(int id, int number) {
String sql = "UPDATE account SET count1=count1+? where id=?";
jdbcTemplate.update(sql, number, id);
} public void subMoney(int id, int number) throws Exception {
if ((this.getCount(id) - number) < 0) {
throw new Exception();
} String sql = "UPDATE account SET count1=count1-? where id=?";
jdbcTemplate.update(sql, number, id); } //编程式
public void transactionMoney(int id1, int id2, int money) { // transactionTemplate.setIsolationLevel(1);
// transactionTemplate.setPropagationBehavior(2);//等等
// 是权限之类的设置,但是添加后出现错误? 为什么 不知道 再看看 transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override
protected void doInTransactionWithoutResult(TransactionStatus statu) {
try {
addMoney(id1, money);
subMoney(id2, money);
} catch (Exception e) {
statu.setRollbackOnly();
e.printStackTrace();
} }
}); } //声明式一
public void transactionMoney2(int id1, int id2, int money) throws Exception { addMoney(id1, money);
subMoney(id2, money);
//千万千万不能再try catch里面捕获,不让相当于他觉得你已经处理了,所以不会正确回滚,并且,他默认
//只能在跑出RuntimeException的时候才会回滚,像这里的Exception 需要在xml文件里面加入rollback-for="Exception"。 } //声明式二
@Transactional(rollbackFor=Exception.class)//同理上面,这里也需要指定为Exception抛出异常也必须回滚。还有很多属性可以设置,比如time什么的。
public void transactionMoney3(int id1, int id2, int money) throws Exception { addMoney(id1, money);
subMoney(id2, money); } } //测试单元如下
@Test
public void testAccountDao() throws Exception{
//之前先捕获accountDao
accountDao.transactionMoney3(1, 3, 15); }
Spring学习六(事物管理)的更多相关文章
- Spring学习8-Spring事务管理
http://blog.sina.com.cn/s/blog_7ffb8dd501014e0f.html Spring学习8-Spring事务管理(注解式声明事务管理) 标签: spring注 ...
- Spring中的事物管理----HelloWorld
在学习Spring的事物管理之前明白先明白几个概念1什么是事物:事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用例子说明:例如银行转账,A账户转账(转2 ...
- Spring中的事物管理,基于spring的bean的配置
很多东西与上边的相同,这儿只简介: 导包... 数据库中建立三个表... 建立存放连接数据库的file文件:jdbc.properties: ----------------------------- ...
- Spring中的事物管理,用 @Transactional 注解声明式地管理事务
事物: 事务管理是企业级应用程序开发中必不可少的技术, 用来确保数据的 完整性和 一致性. 事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用 事务的四 ...
- Spring学习(六)-----Spring使用@Autowired注解自动装配
Spring使用@Autowired注解自动装配 在上一篇 Spring学习(三)-----Spring自动装配Beans示例中,它会匹配当前Spring容器任何bean的属性自动装配.在大多数情况下 ...
- spring学习 六 spring与mybatis整合
在mybatis学习中有两种配置文件 :全局配置文件,映射配置文件.mybatis和spring整合,其实就是把mybatis中的全局配置文件的配置内容都变成一个spring容器的一个bean,让sp ...
- Spring学习8-Spring事务管理(注解式声明事务管理)
步骤一.在spring配置文件中引入<tx:>命名空间 <beans xmlns="http://www.springframework.org/schema/beans& ...
- Spring学习8-Spring事务管理(AOP/声明式式事务管理)
一.基础知识普及 声明式事务的事务属性: 一:传播行为 二:隔离级别 三:只读提示 四:事务超时间隔 五:异常:指定除去RuntimeException其他回滚异常. 传播行为: 所谓事务的传播行为 ...
- Spring学习8-Spring事务管理(编程式事务管理)
一.Spring事务的相关知识 1.事务是指一系列独立的操作,但在概念上具有原子性. 比如转账:A账号-100, B账号+100,完成.这两个操作独立是没问题的. 但在逻辑上,要么全部完成,要么一 ...
随机推荐
- 『TensorFlow』SSD源码学习_其四:数据介绍及TFR文件生成
Fork版本项目地址:SSD 一.数据格式介绍 数据文件夹命名为VOC2012,内部有5个子文件夹,如下, 我们的检测任务中使用JPEGImages文件夹和Annotations文件夹. JPEGIm ...
- 【Java】【4】关于Java中的自增自减
摘要:理解j = j++与j = ++j的区别:正确用法:直接用j++,不要用前两种 正文: import java.util.*; public class Test{ public static ...
- python写网络爬虫的环境搭建
网上找了好多资料,都不全,通过资料的整理,包括自己的测试,终于把环境打好了,真是对于一个刚接触爬虫的人来说实属不易,现在分享给大家,若有不够详细之处,希望各位网友能补充. 第一步,下载python, ...
- DBMS_ROWID定位数据行物理存储位置
对于Oracle中的堆表,我们可以通过oracle内置的ROWID伪列得到对应行记录所在的ROWID的值(注意,这个ROWID只是一个伪列,实际的块中并不存在该列).然后我们可以通过DBMS_ROWI ...
- Hadoop介绍-2.分布式计算框架Hadoop原理及架构全解
Hadoop是Apache软件基金会所开发的并行计算框架与分布式文件系统.最核心的模块包括Hadoop Common.HDFS与MapReduce. HDFS HDFS是Hadoop分布式文件系统(H ...
- ADO.NET json数组多条记录执行在DAL层循环(执行存储过程)
public int UpdateRegdate(tj_book_patient regdatejson) { int temp; SqlParameter[] ps = new SqlParamet ...
- Buffer和Stream
Buffer JavaScript 语言自身只有字符串数据类型,没有二进制数据类型.但在处理像TCP流或文件流时,必须使用到二进制数据. 因此在 Node.js中,定义了一个 Buffer 类,该类用 ...
- asm ftp utilty and usage
Oracle 11g ASM supports ASM FTP, by which operations on ASM files and directories can be performed s ...
- 再谈数据库优化(database tuning)的真谛和误区
当今各行业信息量呈现爆炸式增长,因此,数据库优化也就显得弥足重要.随着数据库性能问题的出现,每位用户为了解决出现的问题,不得不满网上到处搜索优化的”灵丹妙药“和捷径,于是,就出现了各种各样的条条框框和 ...
- Django之路由分配系统
前言: Django大致工作流程 1.客户端发送请求(get/post)经过web服务器.Django中间件. 到达路由分配系统 2.路由分配系统根据提取 request中携带的的url路径(path ...