Spring事务管理
来源:互联网 发布:mac vnc 编辑:程序博客网 时间:2024/06/14 14:37
Spring事务管理
事务
- 含义:
- 访问并可能更新数据库中各种数据项的一个程序执行单元(unit),是一个序列的对数据库的读/写的操作。
- 目的:
- 保证用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性。
- 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
- 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。
- 特性:
- 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
- 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
- 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
- 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。
Spring事务管理
- 方式
- 编程式事务管理(精确控制事务边界)
- 声明式事务管理(低耦合)
事务管理器
DataSourceTransactionManager:用于Spring对JDBC抽象的支持,也可用于iBATIS进行持久化的场景。
<!-- JDBC事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 属性为引用了一个id为dataSource的bean--> <property name="dataSource" ref="dataSource"/></bean>
DataSourceTransactionManager通过调用
java.sql.Connection
来管理事务,后者是通过DataSource获取的,通过调用连接的commit()
方法来提交事务。事务失败,则调用其rollback()
方法进行回滚。- HibernateTransactionManager:用于对Hibernate进行持久化
sessionFactory需要装配一个Hibernate的SessionFactory。 - JpaTransactionManager:用于对Java持久化API进行持久化
- JtaTransactionManager:用于分布式事务,如:跨多个事务资源(一个以上数据库)
一个转账示例(伪代码)
业务层的转账方法代码
public void transferMoney(String from, String to, double money) { //调用持久层Dao类的相关方法 //outMoney():转出方法 inMoney():转入方法 accountDao.outMoney(from, money); accountDao.inMoney(to, money);} @Testpublic void testTransfer() { //调用业务层的转账方法 accountService.transferMoney("lily", "lucy", 200d);}
上边这个转账方法就必须进行事务管理,要么成功,要么失败。但是,如果
public void transferMoney(String from, String to, double money) { //调用持久层Dao类的相关方法 //outMoney():转出方法 inMoney():转入方法 accountDao.outMoney(from, money); int i = 10 / 0;//这里出现异常 accountDao.inMoney(to, money);}
转账期间出现异常时,转账失败,造成钱转出,对方却没收到的情况,so,交给事务吧!
+ 采用编程式事务管理
+ 首先,我们需要使用Spring的TransactionTemplate来添加事务边界,TransactionTemplate提供了一种回调机制。在配置文件中注入TransactionTemplate
<!-- 配置c3p0连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driverClass}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- 加载jdbc的属性文件 --> <context:property-placeholder location="classpath:db.properties"/> <!-- 配置Dao层类 --> <bean id="accountDao" class="com.mvbin.dao.AccountDaoImpl"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 配置业务层类 --> <bean id="accountService" class="com.mvbin.service.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> <property name="transactionTemplate" ref="transactionTemplate"/> </bean> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <!-- 需要注入transactionManager --> <property name="transactionManager" ref="transactionManager"/> </bean> <!-- JDBC事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 属性为引用了一个id为dataSource的bean--> <property name="dataSource" ref="dataSource"/> </bean> + 其次,修改`transferMoney()` public void transferMoney(final String from, final String to, final double money) { /*set注入transactionTemplate * 调用execut(),传入TransactionCallback<T>对象,匿名内部类 * */ transactionTemplate.execute(new TransactionCallback<String>() { public String doInTransaction(TransactionStatus txStatus) { try { accountDao.outMoney(from, money); int i = 10 / 0;//异常 accountDao.inMoney(to, money); } catch (RuntimeException e) { txStatus.setRollbackOnly(); throw e; } return ""; } }); }这种就是编程式事务管理了,对程序有较大的侵入性
+ 采用声明式事务管理:通过事务属性进行定义,通过AOP框架进行实现。
+ 事务属性
+ 传播行为
+ 隔离级别
+ 回滚规则
+ 事务超时
+ 是否只读
+ 使用tx命名空间配置事务
<!-- 配置事务:配置所需管理器,配置事务属性 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- 事务属性配置 --> <!-- name: 方法名称,可用通配符进行匹配一系列方法 isolation: 事务隔离级别 propagation: 事务传播行为 read-only: 事务是否只读 timeout: 定义事务超时时间 no-rollback-for:对于指定异常出现时不进行回滚 rollback-for: 对于指定异常出现时进行回滚 --> <tx:attributes> <!-- 以 transfer开头的方法需要在事务中运行--> <tx:method name="transfer*" propagation="REQUIRED"/> <!-- 其他方法,如果存在当前事务,就在事务中运行,否则不运行 --> <tx:method name="*" propagation="SUPPORTS"/> </tx:attributes> </tx:advice> <!-- 定义一个通知器 --> <aop:config> <!-- advice-ref:应用一个通知 pointcut:定义一个切面,以AspectJ切入点表达式来声明通知器适用于com.mvbin.service.AccountService接口中的所有方法 --> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.mvbin.service.AccountService.*(..))"/> </aop:config>+ 通过注解驱动配置事务 <!-- 配置这样一句话即可,注解驱动会检查Spring上下文中所有的Bean,并找出使用@Transactional注解 的Bean,不管这个注解是在类上还是方法上,<tx:annotation-driven>会自动为其添加事务通知。 通知事务的属性通过@Transactional注解的参数来定义的。 --> <tx:annotation-driven transaction-manager="transactionManager"/>业务类代码 @Transactional(propagation=Propagation.SUPPORTS, readOnly=true) public class AccountServiceImpl implements AccountService { private AccountDaoImpl accountDao; private TransactionTemplate transactionTemplate; @Transactional(propagation=Propagation.REQUIRED, readOnly=false) public void transferMoney(final String from, final String to, final double money) { //此处省略一万行代码。。。。 }
0 0
- 事务管理之Spring事务管理
- Spring事务管理
- spring事务管理
- Spring事务管理
- Spring事务管理
- Spring事务管理
- Spring事务管理
- Spring事务管理
- Spring 事务管理
- Spring事务管理
- spring 事务管理
- spring 事务管理
- spring 事务管理
- spring事务管理
- Spring 事务管理
- Spring事务管理
- spring事务管理
- spring 事务管理
- ASP.NET MVC基于标注特性的Model验证:ValidationAttribute
- sha256
- mongoDB Cannot start server. The default storage engine 'wiredTiger' is not available
- Java中super的几种用法并与this的区别
- php 追加内容到txt文件中
- Spring事务管理
- jQuery学习笔记
- AutoIT 实现Firefox上传文件
- 学习笔记(九)MFC修改屏幕分辨率
- java方法重写和重载
- 使用Python进行简单的图像处理
- viewpager滑动时下面的圆点跟着滑动的代码实现
- 为什么在12306买火车票要装根证书?
- NEUOJ 720 (字典树+LCA || 二分+哈希)