参考链接

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,没有超时限制。

事务只读属性

      只读事务用于客户代码只读但不修改数据的情形,只读事务用于特定情景下的优化,比如使用Hibernate的时候。
默认为读写事务。

“只读事务”并不是一个强制选项,它只是一个“暗示”,提示数据库驱动程序和数据库系统,这个事务并不包含更改数据的操作,那么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学习六(事物管理)的更多相关文章

  1. Spring学习8-Spring事务管理

      http://blog.sina.com.cn/s/blog_7ffb8dd501014e0f.html   Spring学习8-Spring事务管理(注解式声明事务管理) 标签: spring注 ...

  2. Spring中的事物管理----HelloWorld

    在学习Spring的事物管理之前明白先明白几个概念1什么是事物:事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用例子说明:例如银行转账,A账户转账(转2 ...

  3. Spring中的事物管理,基于spring的bean的配置

    很多东西与上边的相同,这儿只简介: 导包... 数据库中建立三个表... 建立存放连接数据库的file文件:jdbc.properties: ----------------------------- ...

  4. Spring中的事物管理,用 @Transactional 注解声明式地管理事务

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

  5. Spring学习(六)-----Spring使用@Autowired注解自动装配

    Spring使用@Autowired注解自动装配 在上一篇 Spring学习(三)-----Spring自动装配Beans示例中,它会匹配当前Spring容器任何bean的属性自动装配.在大多数情况下 ...

  6. spring学习 六 spring与mybatis整合

    在mybatis学习中有两种配置文件 :全局配置文件,映射配置文件.mybatis和spring整合,其实就是把mybatis中的全局配置文件的配置内容都变成一个spring容器的一个bean,让sp ...

  7. Spring学习8-Spring事务管理(注解式声明事务管理)

    步骤一.在spring配置文件中引入<tx:>命名空间 <beans xmlns="http://www.springframework.org/schema/beans& ...

  8. Spring学习8-Spring事务管理(AOP/声明式式事务管理)

    一.基础知识普及 声明式事务的事务属性: 一:传播行为 二:隔离级别 三:只读提示 四:事务超时间隔 五:异常:指定除去RuntimeException其他回滚异常.  传播行为: 所谓事务的传播行为 ...

  9. Spring学习8-Spring事务管理(编程式事务管理)

    一.Spring事务的相关知识   1.事务是指一系列独立的操作,但在概念上具有原子性. 比如转账:A账号-100, B账号+100,完成.这两个操作独立是没问题的. 但在逻辑上,要么全部完成,要么一 ...

随机推荐

  1. uva11388

    因为a,b整除gcd(a,b),lcm(a,b)又整除a,b,因此如果lcm不整除gcd就是-1:否则的话,lcm=a*b/gcd.而a不能小于gcd,因此a就取gcd,b取lcm. #include ...

  2. android -------- 错误Attribute application@allowBackup value=(true) from AndroidManifest.xml

    开发中遇到一个问题,运行项目时,出现了一个这如下这样的问题 问题: Manifest merger failed : Attribute application@allowBackup value=( ...

  3. CF903G Yet Another Maxflow Problem

    考虑最大流=最小割 不妨把a到a的边称为a类边,b到b的称为b类边,a到b的称为c类边. 显然,答案一定是由最多1条a和最多一条b以及一些c组成的. 只有a是会变的,也就是说每个a对应了唯一的最优的b ...

  4. eth

    今天说下Centos的eth0:0这个虚拟端口,应为学到ifcofig eth0:0 IP,可以给一个网卡设置俩个IP地址,但是只是临时设置,然而我想永久设置,所以就在网找,最终找到的方法是 可以先复 ...

  5. Symmetric Tree leetcode java

    问题描述: Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). ...

  6. python记录_day11 闭包 迭代器

    一.第一类对象: 函数名是一个变量,可以当普通变量使用,但它又是一个特殊的变量,与括号配合可以执行函数. 函数名的运用 1.单独打印是一个内存地址 2.可以给其他变量赋值 3.可以作为容器类变量的元素 ...

  7. 让你明白kvm是什么

    参考:https://blog.csdn.net/bbwangj/article/details/80465320 KVM 工具集合: libvirt:操作和管理KVM虚机的虚拟化 API,使用 C ...

  8. PAT 1009 Product of Polynomials

    1009 Product of Polynomials (25 分)   This time, you are supposed to find A×B where A and B are two p ...

  9. Oracle 11.2.0.4.0 Dataguard部署和日常维护(2)-Datauard部署篇

    1. primary库设置dataguard相关参数   1.1. 强制primay库在任何状态下必须记录日志 SYS@userdata>select FORCE_LOGGING from v$ ...

  10. [luogu P1438] 无聊的数列

    [luogu P1438] 无聊的数列 题目背景 无聊的YYB总喜欢搞出一些正常人无法搞出的东西.有一天,无聊的YYB想出了一道无聊的题:无聊的数列...(K峰:这题不是傻X题吗) 题目描述 维护一个 ...