知识大全 Spring的事务
Posted 知
篇首语:学者有自立之志,当拔出流俗,不可泛泛与世浮沉。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 Spring的事务相关的知识,希望对你有一定的参考价值。
Spring的事务 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
今天对 spring 的 AOP 事务有了一个新的认识 所以赶紧把今天的学习记下来 希望在今后的学习中能够起到一些作用 也能对今天的认识做一次总结
spring 分享
先看一段代码
Connection conn = Conn getConnection();
conn setAutoCommit(false);
……
……
conn rollback();
mit();
数据库的事务是针对 Connection 的
接着再看一段代码 ( spring 中事务的一段学习代码 这段代码是把 spring 和 hibernate 结合在一起的 增加了理解上的难度 因为我的出发点一开始不要 hibernate 就光用 jdbc 来进行数据库事务 但是没有其他好的代码 就这样吧)
public Long addLineItem(Long orderId LineItem lineItem)
log( OrderListDAOHibernate addLineItem : Start );
OrderList orderList = (OrderList) getHibernateTemplate() load(OrderList class orderId);
lineItem setOrderList(orderList);
getHibernateTemplate() saveOrUpdate(lineItem);
getHibernateTemplate() saveOrUpdate(orderList);
log( OrderListDAOHibernate addLineItem : Ending );
return lineItem getId();
在这个代码的配置文件中 把 addLineItem 做为一个切入点 进行事务 也就是说 在 addLineItem 的外面 再包上一层事务的外壳
但是这个时候 问题出来了 事务是针对 Connection 的 而上面的两个连续的 HibernateTemplate 执行的 saveOrUpdate 中的 Connection 必须是一致才能用事务 spring 怎么做到这一点的呢?(这个问题也就是在找 spring 的事务例子前 我想的 spring 中用 jdbc 来进行事务 怎么样让 Connection 保持一致呢?但是没有 jdbc 的例子 只有整合 hibernate 或者 ibatis 的例子 但是 我想 原理是一样的吧 )
解决问题的思路 HibernateTemplate 中的 Connection 必定一致 那么就从 HibernateTemplate 入手
看 spring 的源代码 既然是 Hibernate 那么 就没有 Connection 给你看 只有 Session 由 Session 来管理 Connection 那么用事务来控制的话 这个 Session 必定在所有该事务中是一致的 于是在 HibernateTemplate 中找到
protected Session getSession()
if (isAlwaysUseNewSession())
return SessionFactoryUtils getNewSession(getSessionFactory() getEntityInterceptor());
else if (!isAllowCreate())
return SessionFactoryUtils getSession(getSessionFactory() false);
else
return SessionFactoryUtils getSession(
getSessionFactory() getEntityInterceptor() getJdbcExceptionTranslator());
看来在 SessionFactoryUtils 里面 接着在 SessionFactoryUtils getSession 中找
这个方法太长了 太复杂了 从简 发现了非常关键的一点
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager getResource(sessionFactory);
假如 sessionHolder 不等于空 说明 在事务中有这样一个还没有 mit 的 session 那么就返回这个 session 假如等于空 新建一个 session 并且在事务里加入这个 session 这段代码的意思大概是这样 太繁杂了 只能猜 也肯定是如此
再看 getHibernateTemplate() 方法来自继承 HibernateDaoSupport 看了电子书《 spring reference 》的第九章 Dao 支持 Dao 的支持类可以有好多 如 JdbcDaoSupport HibernateDaoSupport JdoDaoSupport 等等
既然前面一开始就是从 jdbc 的 spring 事务控制引起的 那么看到了同样的 HibernateDaoSupport JdbcDaoSupport 那么 JdbcDaoSupport 也应该有 getJdbcTemplate() 这个方法 并且返回 JdbcTemplate 这个类
果然如此
于是剖析 JdbcTemplate 是不是和 HibernateTemplate 一样 果然一样
注意到
Connection con = DataSourceUtils getConnection(getDataSource());
Connection 是从 DataSourceUtils getConnection() 来的 继续跟踪 DataSourceUtils getConnection()
找到
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager getResource(dataSource);
和 Hibernate 中的一模一样 因为没有了 session 的封装 条理在 jdbc 中更加清晰了
至此 spring 的事务控制 已经全部搞定
Spring 事务管理的配置
看了上面同事学习 spring 的笔记后自己也觉得有新的理解 从什么地方说起呢?就从 spring 的事务配置说起吧 那么我们看看 contextConfig xml 吧
<bean id= sessionFactory class= springframework orm hibernate LocalSessionFactoryBean >
<property name= dataSource >
<ref bean= dataSource />
</property>
<property name= mappingResources >
<list>
<value>mf//user/User hbm xml</value>
</list>
</property>
</bean>
<bean id= transactionManager class= springframework orm hibernate HibernateTransactionManager >
<property name= sessionFactory >
<ref local= sessionFactory />
</property>
</bean>
<bean id= txProxyTemplate abstract= true class= springframework transaction interceptor TransactionProxyFactoryBean >
<property name= transactionManager >
<ref bean= transactionManager />
</property>
<property name= transactionAttributes >
<props>
<prop key= save* >PROPAGATION_REQUIRED Exception</prop>
<prop key= remove* >PROPAGATION_REQUIRED Exception </prop>
<prop key= update* >PROPAGATION_REQUIRED Exception </prop>
<prop key= incress* >PROPAGATION_REQUIRED Exception </prop>
<prop key= * >PROPAGATION_REQUIRED readOnly</prop>
</props>
</property>
</bean>
<bean id= userManager parent= txProxyTemplate >
<property name= target ref= userManagerTarget />
</bean>
<bean id= userManagerTarget
class= hb user service impl UserManagerImpl >
<property name= userDAO ref= userDAO />
</bean>
<bean id= userDAO class= hb user dao hibernate UserDAOHibernate >
<property name= sessionFactory ref= sessionFactory />
</bean>
以上就是一个完整的 spring 配置 是不是很熟悉呢 这里是用的 Appfuse 的框架 呵呵 有那么点味道吧
首先我们看看
<bean id= transactionManager class= springframework orm hibernate HibernateTransactionManager >
<property name= sessionFactory >
<ref local= sessionFactory />
</property>
</bean>
这一个 bean 让 spring 为我们注入了什么呢?事务 对!我们把 hibernate 的事务注入到了 spring 的 IOC 容器之中了 然后我们再看看
<bean id= txProxyTemplate abstract= true class= springframework transaction interceptor TransactionProxyFactoryBean >
<property name= transactionManager >
<ref bean= transactionManager />
</property>
<property name= transactionAttributes >
<props>
<prop key= save* >PROPAGATION_REQUIRED Exception</prop>
<prop key= remove* >PROPAGATION_REQUIRED Exception </prop>
<prop key= update* >PROPAGATION_REQUIRED Exception </prop>
<prop key= incress* >PROPAGATION_REQUIRED Exception </prop>
<prop key= * >PROPAGATION_REQUIRED readOnly</prop>
</props>
</property>
</bean>
这个 bean 又是让 spring 为我们注入了了什么呢?事务代理 对了!我们把事务的代理交给一个 txProxyTemplate 的去做了 这样的好处我待会再说 现在我们看看下面的一些配置信息
<prop key= save* >PROPAGATION_REQUIRED Exception</prop>
<prop key= remove* >PROPAGATION_REQUIRED Exception </prop>
<prop key= update* >PROPAGATION_REQUIRED Exception </prop>
<prop key= incress* >PROPAGATION_REQUIRED Exception </prop>
<prop key= * >PROPAGATION_REQUIRED readOnly</prop>
这里就是事务处理时如果遇到异常信息 或者其他的原因时我们要求 spring 把当前的事务回滚了 这样才能不至于在数据库中产生垃圾啊 我们规定所有的 save remove update incress 这样的方法开头的在出现一些问题后把事务给回滚了 看看我们写的 PROPAGATION_REQUIRED Exception
有人就会说 PROPAGATION_REQUIRED 就可以回滚事务啊 为什么加上 Exception 呢?其实我以前也时这样想的 但这是不完全正确的 当然我们在处理一个事务时只要有一个 PROPAGATION_REQUIRED 就可以了 但是当我们的业务逻辑中要求我们在一个事务代理中开启两个事务 这两个事务表面上没有联系 但是实际中又有很多联系的 比如我们上传附件和提交文档 这样两个操作我们可以分开 因为他们不是往一个表里插入数据 我们又不希望这两个操作写在一个 service 里 这样我们要是有一个业务只要上传附件呢?那样我们是不是又要再写一个方法啊!所以在开启两个事务时如果有一个抛出异常了 我们就要把上一个提交的事务回滚了 这样做我们就要用的 Exception 了 这样就完全满足我们的要求了 我也试过如果我写的是 PROPAGATION_REQUIRED SQLException 时 这样我们只会在出现 SQLException 时事务回顾 出现其他的异常事务就不回滚了 好在 spring 可以让我们写如异常的基类就可以做到捕获任何异常 这样我们就写 Exception 好了 特殊情况在特殊处理吧 通用情况下我们还是这样的
我们再看看
<bean id= userManager parent= txProxyTemplate >
<property name= target ref= userManagerTarget />
</bean>
<bean id= userManagerTarget
class= hb user service impl UserManagerImpl >
<property name= userDAO ref= userDAO />
</bean>
<bean id= userDAO class= hb user dao hibernate UserDAOHibernate >
<property name= sessionFactory ref= sessionFactory />
</bean>
当然我们也可以写成
<bean id= userManager parent= txProxyTemplate >
<property name= target >
<bean class= hb user service impl UserManagerImpl >
<property name= userDAO >
<ref bean= userDao />
</property>
</bean>
</property>
</bean>
<bean id= userDAO class= hb user dao hibernate UserDAOHibernate >
<property name= sessionFactory ref= sessionFactory />
</bean>
这下我们解除以前的疑惑 parent= txProxyTemplate 知道我们为什么在上面先写了 txProxyTemplate 的 bean 了吧 这样我们就没有必要再写一编了 是不是很方便? spring 的这些技巧还不只这些呢 这样我们就可以轻松利用以上这三个注入的类去做我们的逻辑了
Spring 就是要我们注入实现类 然后使用接口操作 这样耦合性就不是那么强了 这也体现了 Spring 的工厂模式 而 AOP 的 manager 又象我们熟知的代理模式吧 !
注意要点
cha138/Article/program/Java/ky/201311/28161相关参考
Spring声明式事务管理源码解读之事务开始 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 在s
Spring事务管理 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 数据库事务是由一系列的动作组
<!构建HibernateTransactionManager用于获得session管理事务> <beanid=transactionManagerclass=springfr
Spring+Ibatis+事务处理 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! applic
Spring事务深入浅出 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &n
浅析Spring提供的事务管理方法 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! Spring提
Spring中事务的传播属性详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 我们用Sprin
Spring中的事务传播属性详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 在使用Sprin
Spring中的四种声明式事务的配置 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! Spring
在Spring中配置Hibernate的事务 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 本文