博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring事务管理(Transaction)
阅读量:6139 次
发布时间:2019-06-21

本文共 4790 字,大约阅读时间需要 15 分钟。

  hot3.png

事务概述

        数据库事务(Transaction) 指作为单个逻辑工作单元执行的一系列操作。将一组相关操作组合为一个要么全部成功要么全部失败的单元,使应用程序更加可靠。

事务必须满足ACID:

  • n原子性(Atomicity),对于其数据修改,要么全都执行,要么全都不执行
  • n一致性(Consistency) 事务在完成时,必须使所有数据保持一致。
  • n隔离性(Isolation) 并发事务所作修改须与任何其它并发事务所作的修改隔离
  • n持久性(Durability) 在事务完成后,该事务对数据库所作更改持久保存在数据库中,并不会回滚。即使出现任何事故比如断电等,事务一旦提交也持久化保存在数据库。

Spring事务管理方式

编程式事务管理

        可清楚定义事务边界,实现细粒度的事务控制,比如可通过程序代码来控制事务何时开始、何时结束等,可实现细粒度事务控制。

声明式事务管理

         如不需要细粒度的事务控制,可使用声明式事务,只需在Spring配置文件做一些配置即可将操作纳入到事务管理中,解除与代码的耦合, 对应用代码影响最小。当不需事务管理时,可直接从Spring配置文件中移除该设置。

事务管理器

        spring不直接管理事务,而将管理事务责任委托给JTA或相应持久性机制提供的特定平台的事务实现

事务管理器实现 场合

org.springframework.jdbc.datasource.DataSourceTransactionManager

在单一JDBC Datasource中管理事务

org.springframework.orm.hibernate3.HibernateTransactionManager

持久化机制为hibernate

org.springframework.jdo.JdoTransactionManager

持久化机制为Jdo

org.springframework.transaction.jta.JtaTransactionManager

使用一个JTA实现来管理事务。一个事务跨越多个资源时必须使用

org.springframework.orm.ojb.PersistenceBrokerTransactionManager

持久化机制为apache的ojb

事务属性(propagation、isolation、read-only)

事务传播规则(propagation)

        传播行为:定义关于客户端和被调用方法的事务边界

传播行为

含    义

REQUIRED

业务方法需在一个事务中运行。如方法运行时已处在一事务中,则加入到该事务,否则为自己创建一个新事务

NOT_SUPPORTED

声明方法不需事务。如方法没有关联到一事务,容器不会为它开启事务;如方法在一事务中被调用,该事务被挂起,在方法调用结束后,原事务恢复执行

REQUIRESNEW

不管是否存在事务,业务方法总会为自己发起一新事务。如方法已运行在一个事务中,则原有事务会被挂起,新的事务会被创建,直到方法执行结束,新事务才算结束,原事务才恢复执行

MANDATORY

指定业务方法只能在一个已存在事务中执行,业务方法不能发起自己事务。如业务方法在没有事务的环境调用,容器抛出异常。

SUPPORTS

如业务方法在某个事务范围内被调用,则方法成为该事务的一部分。如业务方法在事务范围外被调用,则方法在没有事务的环境下执行

Never

指定业务方法绝对不能在事务范围内执行,如业务方法在某个事务中执行,容器抛出异常,只有业务方法没有关联到任何事务才能正常执行

NESTED

如一活动事务存在,则运行在一嵌套事务中. 如没有活动事务, 则按REQUIRED属性执行。使用一单独的事务, 该事务拥有多个可回滚保存点。内部事务回滚不会对外部事务造成影响。只对DataSourceTransactionManager事务管理器起效

隔离级别

隔离级别

含义

DEFAULT

使用后端数据库默认的隔离级别

READ_UNCOMMITED

允许读取还未提交的已改变数据,可能导致脏、幻、不可重复读

READ_COMMITTED

允许在并发事务已经提交后读取。可防止脏读,但幻读和 不可重复读仍可发生

REPEATABLE_READ

对相同字段的多次读取一致,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。

SERIALIZABLE

完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。在所有隔离级别中最慢的,典型的通过完全锁定事务涉及的数据表。

注意:随着隔离级别的提高并发性能降低,具体使用那种隔离级别需要视情况而定。

补充:

  • 脏读:一个事务读取了另一个事务改写但还未提交的数据,如这些数据被回滚,则所读数据无效。
  • 不可重复读:在同一事务中,多次读取同一数据返回结果不同,后续读取可读到另一事务已提交更新数据。“可重复读”在同一事务中多次读取数据时,能够保证所读数据一样。
  • 幻读:一个事务读取了几行记录后,另一个事务插入一些记录,再查询时第一个事务会发现原来没有的记录

read-only

        表示该方法是否只读,默认是false(可写)。对数据库执行增、删、改,事务一定要定义可写,对数据库执行查询的时候,此时可以定为只读(true)

声明式事务的配置

        我们采用的是声明式事务管理,配置事务时,需在xml配置文件引入声明事务的tx标签

    事务的配置方式:

  • 基于XML配置方式
  • 注解方式

Spring+JDBC组合开发(配置事务xml方式)

参考代码如下:

 

Spring+JDBC组合开发(注解方式配置事务)

参考代码如下:

beans.xml

BankAccountServiceImpl.java

package www.enfp.lx_04_jdbc.lx_01_transaction_annotation.service;import javax.annotation.Resource;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Isolation;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import www.enfp.lx_04_jdbc.lx_01_transaction_xml.dao.IBankAccountDao;import www.enfp.lx_04_jdbc.lx_01_transaction_xml.domain.BankAccount;@Service("bankAccountService")@Transactional(readOnly = true)public class BankAccountServiceImpl implements IBankAccountService{	@Resource(name = "bankAccountDao")	private IBankAccountDao bankAccountDao = null;	public IBankAccountDao getBankAccountDao()	{		return bankAccountDao;	}	public void setBankAccountDao(IBankAccountDao bankAccountDao)	{		this.bankAccountDao = bankAccountDao;	}	@Override	@Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, readOnly = false)	public boolean transferBankAccount(String firstBankAccountName,			String secondBankAccountName, double money)	{		try		{			if (money < 0)			{				throw new RuntimeException("转账金额必须为正数");			}			BankAccount accountA = this.bankAccountDao					.queryBankAccountByAccountName(firstBankAccountName);			if (accountA.getBalance() < money)			{				throw new RuntimeException("余额不足");			}			BankAccount accountB = this.bankAccountDao					.queryBankAccountByAccountName(secondBankAccountName);			accountA.setBalance(accountA.getBalance() - money);			accountB.setBalance(accountB.getBalance() + money);			this.bankAccountDao.updateBankAccount(accountA);			this.bankAccountDao.updateBankAccount(accountB);			return true;		} catch (Exception e)		{			// TODO Auto-generated catch block			e.printStackTrace();		}		return false;	}}

未完待续。。。。。

转载于:https://my.oschina.net/enfp/blog/741928

你可能感兴趣的文章
LeetCode——Nim Game
查看>>
正则表达式入门教程&&经典Javascript正则表达式(share)
查看>>
设计模式聚合和组合--代码执行
查看>>
深入理解Java:注解(Annotation)自定义注解入门
查看>>
网络架构、云平台和微信公众平台开发接入
查看>>
.NET软件开发与常用工具清单(转)
查看>>
windows装了双系统设置默认启动系统
查看>>
数据本地化之文件操作
查看>>
Linux下的网络管理工具—OpenNMS
查看>>
Java 8 VM GC Tuning Guide Charter2
查看>>
子网掩码与子网划分
查看>>
Android访问网络数据的几种方式Demo
查看>>
Spring-AOP
查看>>
转】用Maven构建Hadoop项目
查看>>
SAP自定义权限对象
查看>>
Guava 12-数学运算
查看>>
windows 下搭建简易nginx+PHP环境
查看>>
python 局部变量和全局变量 global
查看>>
windows 下编辑shell,到linux报错,也是windows换行等造成
查看>>
JavaScript 闯关记
查看>>