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,完成.这两个操作独立是没问题的. 但在逻辑上,要么全部完成,要么一 ...
随机推荐
- hbase知识
HBASE是一个高可靠性.高性能.面向列.可伸缩的分布式存储系统 HBASE的目标是存储并处理大型的数据,更具体来说是仅需使用普通的硬件配置,就能够处理由成千上万的行和列所组成的大型数据. HBASE ...
- token原理详解
概念与使用流程 是计算机术语:令牌,令牌是一种能够控制站点占有媒体的特殊帧,以区别数据帧及其他控制帧.token其实说的更通俗点可以叫暗号,在一些数据传输之前,要先进行暗号的核对,不同的暗号被授权不同 ...
- Spring注解之 @EnableScheduling计划任务注解
要实现计划任务,首先通过在配置类注解@EnableScheduling来开启对计划任务的支持, 然后在要执行计划任务的方法上注解@Scheduled,声明这是一个计划任务 示例:计划任务执行类 在这个 ...
- IDEA Activiti Designer插件---actiBPM汉字乱码问题
1.找到IDEA的安装目录 2.用编辑器打开,在文件末尾添加 -Dfile.encoding=UTF-8
- docker 安装nginx、php-fpm
运行环境: 创建目录: mkdir -p /Users/sui/docker/nginx/conf.d && mkdir /Users/sui/www && cd /U ...
- PHP json_encode重要的秘密
php格式化json的函数 json_encode($value,$options) 其中有2个比较常用到的参数 JSON_UNESCAPED_UNICODE(中文不转为unicode ,对应的数字 ...
- Oracle常用表和常见操作命令
一.说明 Oracle数据库数据库名.表名.字段名等不区分大小写,字段值区分大小写. Oracle单词之间一般用下划线连接:表名最后一般加s字段名最后一般没s. 二.常见数据表 dba_*DBA拥有的 ...
- 整合Spring Security(二十七)
在这一节,我们将对/hello页面进行权限控制,必须是授权用户才能访问.当没有权限的用户访问后,跳转到登录页面. 添加依赖 在pom.xml中添加如下配置,引入对Spring Security的依赖. ...
- linux定时删除文件脚本
#! /bin/sh # 配置项DEBUG=truefolderDir=/var/www/html/hlsrecord/EXPIRE_DAY=1 # 过期时间和时间戳deadTime=`date -d ...
- 转: Linux mount/unmount命令
https://blog.csdn.net/okhymok/article/details/76616892 楼主具体哪里转的 我不清楚 好像没看到原始出处 开机自动挂载 如果我们想实现开机自动挂载某 ...