[转]Spring的事务管理难点剖析(1):DAO和事务管理的牵绊
原文地址:http://stamen.iteye.com/blog/1441758
有些人很少使用Spring而不使用Spring事务管理器的应用,因此常常有人会问:是否用了Spring,就一定要用Spring事务管理器,否则就无法进行数据的持久化操作呢?事务管理器和DAO是什么关系呢?
也许是DAO和事务管理如影随行的缘故吧,这个看似简单的问题实实在在地存在着,从初学者心中涌出,萦绕在老手的脑际。答案当然是否定的!我们都知道:事
务管理是保证数据操作的事务性(即原子性、一致性、隔离性、持久性,即所谓的ACID),脱离了事务性,DAO照样可以顺利地进行数据的操作。
JDBC访问数据库
下面,我们来看一段使用Spring JDBC进行数据访问的代码:
- package com.baobaotao.withouttx.jdbc;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.jdbc.core.JdbcTemplate;
- import org.springframework.stereotype.Service;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- import org.apache.commons.dbcp.BasicDataSource;
- @Service("userService")
- public class UserJdbcWithoutTransManagerService {
- @Autowired
- private JdbcTemplate jdbcTemplate;
- public void addScore(String userName,int toAdd){
- String sql = "UPDATE t_user u SET u.score = u.score + ? WHERE user_name =?";
- jdbcTemplate.update(sql,toAdd,userName);
- }
- public static void main(String[] args) {
- ApplicationContext ctx = new
- ClassPathXmlApplicationContext("com/baobaotao/withouttx/jdbc/jdbcWithoutTx.xml");
- UserJdbcWithoutTransManagerService service =
- (UserJdbcWithoutTransManagerService)ctx.getBean("userService");
- JdbcTemplate jdbcTemplate = (JdbcTemplate)ctx.getBean("jdbcTemplate");
- BasicDataSource basicDataSource = (BasicDataSource)jdbcTemplate.getDataSource();
- //①检查数据源autoCommit的设置
- System.out.println("autoCommit:"+ basicDataSource.getDefaultAutoCommit());
- //②插入一条记录,初始分数为10
- jdbcTemplate.execute("INSERT INTO t_user(user_name,password,score,last_logon_time)
- VALUES('tom','123456',10,"+System.currentTimeMillis()+")");
- //③调用工作在无事务环境下的服务类方法,将分数添加20分
- service.addScore("tom",20);
- //④查看此时用户的分数
- int score = jdbcTemplate.queryForInt(
- "SELECT score FROM t_user WHERE user_name ='tom'");
- System.out.println("score:"+score);
- jdbcTemplate.execute("DELETE FROM t_user WHERE user_name='tom'");
- }
- }
其中,jdbcWithoutTx.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:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
- <context:component-scan base-package="com.baobaotao.withouttx.jdbc"/>
- <context:property-placeholder location="classpath:jdbc.properties"/>
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
- destroy-method="close"
- p:driverClassName="${jdbc.driverClassName}"
- p:url="${jdbc.url}"
- p:username="${jdbc.username}"
- p:password="${jdbc.password}"/>
- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
- p:dataSource-ref="dataSource"/>
- </beans>
运行UserJdbcWithoutTransManagerService,在控制台上打出如下的结果:
defaultAutoCommit:true
score:30
在jdbcWithoutTx.xml中,没有配置任何事务管理器,但是数据已经成功持久化到数据库中。在默认情况下,dataSource数据源的
autoCommit被设置为true——这也意谓着所有通过JdbcTemplate执行的语句马上提交,没有事务。如果将dataSource的
defaultAutoCommit设置为false,再次运行UserJdbcWithoutTransManagerService,将抛出错误,原
因是新增及更改数据的操作都没有提交到数据库,所以代码清单10-1④处的语句因无法从数据库中查询到匹配的记录而引发异常。
对于强调读速度的应用,数据库本身可能就不支持事务:如使用MyISAM引擎的MySQL数据库。这时,无须在Spring应用中配置事务管理器,因为即使配置了,也是没有实际用处的。
Hibernate访问数据库
对于Hibernate来说,情况就有点复杂了。因为Hibernate的事务管理拥有其自身的意义,它和Hibernate一级缓存在密切的关系:当我
们调用Session的save、update等方法时,Hibernate并不直接向数据库发送SQL语句,只在提交事务(commit)或flush
一级缓存时才真正向数据库发送SQL。所以,即使底层数据库不支持事务,Hibernate的事务管理也是有一定好处的,不会对数据操作的效率造成负面影
响。所以,如果是使用Hibernate数据访问技术,没有理由不配置HibernateTransactionManager事务管理器。
但是,不使用Hibernate事务管理器,在Spring中,Hibernate照样也可以工作,来看下面的例子:
- package com.baobaotao.withouttx.hiber;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.core.io.ClassPathResource;
- import org.springframework.core.io.Resource;
- import org.springframework.jdbc.core.JdbcTemplate;
- import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
- import org.springframework.stereotype.Service;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- import org.springframework.orm.hibernate3.HibernateTemplate;
- import org.apache.commons.dbcp.BasicDataSource;
- import org.springframework.test.jdbc.SimpleJdbcTestUtils;
- import com.baobaotao.User;
- @Service("hiberService")
- public class UserHibernateWithoutTransManagerService {
- @Autowired
- private HibernateTemplate hibernateTemplate;
- public void addScore(String userName,int toAdd){
- User user = hibernateTemplate.get(User.class,userName);
- user.setScore(user.getScore()+toAdd);
- hibernateTemplate.update(user);
- }
- public static void main(String[] args) {
- ApplicationContext ctx = new
- ClassPathXmlApplicationContext("com/baobaotao/withouttx/hiber/hiberWithoutTx.xml");
- UserHibernateWithoutTransManagerService service =
- (UserHibernateWithoutTransManagerService)ctx.getBean("hiberService");
- JdbcTemplate jdbcTemplate = (JdbcTemplate)ctx.getBean("jdbcTemplate");
- BasicDataSource basicDataSource = (BasicDataSource)jdbcTemplate.getDataSource();
- //①检查数据源autoCommit的设置
- System.out.println("autoCommit:"+ basicDataSource.getDefaultAutoCommit());
- //②插入一条记录,初始分数为10
- jdbcTemplate.execute("INSERT INTO t_user(user_name,password,score,last_logon_time)
- VALUES('tom','123456',10,"+System.currentTimeMillis()+")");
- //③调用工作在无事务环境下的服务类方法,将分数添加20分
- service.addScore("tom",20);
- //④查看此时用户的分数
- int score = jdbcTemplate.queryForInt(
- "SELECT score FROM t_user WHERE user_name ='tom'");
- System.out.println("score:"+score);
- jdbcTemplate.execute("DELETE FROM t_user WHERE user_name='tom'");
- }
- }
此时,采用hiberWithoutTx.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:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
- <context:component-scan base-package="com.baobaotao.withouttx.hiber"/>
- …
- <bean id="sessionFactory"
- class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
- p:dataSource-ref="dataSource">
- <property name="annotatedClasses">
- <list>
- <value>com.baobaotao.User</value>
- </list>
- </property>
- <property name="hibernateProperties">
- <props>
- <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
- <prop key="hibernate.show_sql">true</prop>
- </props>
- </property>
- </bean>
- <bean id="hibernateTemplate"
- class="org.springframework.orm.hibernate3.HibernateTemplate"
- p:sessionFactory-ref="sessionFactory"/>
- </beans>
com.baobaotao.User是使用了Hibernate注解的领域对象,代码如下所示:
- package com.baobaotao;
- import javax.persistence.Entity;
- import javax.persistence.Table;
- import javax.persistence.Column;
- import javax.persistence.Id;
- import java.lang.reflect.Field;
- import java.io.Serializable;
- @Entity
- @Table(name="T_USER")
- public class User implements Serializable{
- @Id
- @Column(name = "USER_NAME")
- private String userName;
- private String password;
- private int score;
- @Column(name = "LAST_LOGON_TIME")
- private long lastLogonTime = 0;
- …
- }
运行UserHibernateWithoutTransManagerService,程序正确执行,并得到类似于
UserJdbcWithoutTransManagerService的执行结果。这说明Hibernate在Spring中,在没有事务管理器的情况
下,依然可以正常地进行数据的访问。
注:以上内容摘自《Spring 3.x企业应用开发实战》
[转]Spring的事务管理难点剖析(1):DAO和事务管理的牵绊的更多相关文章
- Spring高级事务管理难点剖析
1Spring事务传播行为 所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播.Spring支持7种事务传播行为 PROPAGATION_REQUIRED(加入已有事务) 如果当前没 ...
- Spring 事务管理高级应用难点剖析: 第 1 部分
Spring 的事务管理是被使用得最多的功能之一,虽然 Spring 事务管理已经帮助程序员将要做的事情减到了最小.但在实际开发中,如果使用不当,依然会造成数据连接泄漏等问题.本系列以实际应用中所碰到 ...
- Spring 事务管理高级应用难点剖析--转
第 1 部分 http://www.ibm.com/search/csass/search/?q=%E4%BA%8B%E5%8A%A1&sn=dw&lang=zh&cc=CN& ...
- Spring 事务管理高级应用难点剖析: 第 3 部分
本文是“Spring 事务管理高级应用难点剖析” 系列文章的第 3 部分,作者将继续深入剖析在实际 Spring 事务管理应用中容易遇见的一些难点,包括在使用 Spring JDBC 时如果直接获取 ...
- Spring 事务管理高级应用难点剖析: 第 2 部分
本文是“Spring 事务管理高级应用难点剖析” 系列文章的第 2 部分,作者将继续深入剖析在实际 Spring 事务管理应用中容易遇见的一些难点,包括混合使用多种数据访问技术(如 Spring JD ...
- Spring事务管理----声明式:利用TransactionProxyFactoryBean生成事务代理
通常建议采用声明式事务管理.声明式事务管理的优势非常明显:代码中无需关于关注事务逻辑,让spring声明式事务管理负责事务逻辑,声明式事务管理无需与具体的事务逻辑耦合,可以方便地在不同事务逻辑之间切换 ...
- JTA事务管理--配置剖析(二)
Spring引用Tomcat的 JTA事务 Tomcat是Servlet容器,但它提供了JNDI的实现,因此用户可以象在Java EE应用程序服务器中一样,在Tomcat中使用JNDI查找JD ...
- JTA事务管理--配置剖析
概述 [IT168 专稿]Spring 通过AOP技术可以让我们在脱离EJB的情况下享受声明式事务的丰盛大餐,脱离Java EE应用服务器使用声明式事务的道路已经畅通无阻.但是很大部分人都还认为 ...
- Spring先进的交易管理困难剖析
1Spring事务传播行为 所谓事务传播行为就是多个事务方法相互调用时,事务怎样在这些方法间传播.Spring支持7种事务传播行为 PROPAGATION_REQUIRED(增加已有事务) 假设当前没 ...
随机推荐
- [转]ng-grid
本文转自:http://angular-ui.github.io/ui-grid/ Getting Started Steps for getting started (example on righ ...
- JSTL基础
是java中的一个定制标记库集 实现了jsp页面中的代码复用,基于标签库原理,重复率较高的代码块支持复用,提高效率 书写jsp页面时可读性更强 http://archive.apache.org/di ...
- java设计模式:单例模式
单例模式:运行期间有且仅有一个实例 1.一个类只有一个实例 2.必须自行创建这个实例 3.必须自行向整个系统提供这个实例 懒汉模式: 在类加载时不创建实例,运行调用时创建.类加载快,在运行时获取对象慢 ...
- nginx集群报错“upstream”directive is not allow here 错误
nginx集群报错“upstream”directive is not allow here 错误 搭建了一个服务器, 采用的是nginx + apache(多个) + php + mysql(两个) ...
- stunnel+CCProxy,搭建加密代理
总所周知,不可抗拒的特别有用心的原因,我们无法访问youtube,picasa,Twitter……国外优秀网站,很多人采用了代理服务器的方法访问. 如果您有一台放在海外的服务器,这个就好办了.下载一个 ...
- [No00002A]26个英语字母的原始象形意义、含义、产生及发展历史
我们都知道汉字是象形文字,但如果说英语也是象形文字,你一定会以为纯是无稽之谈.其实,追根溯源,英语的26个字母确实来自于象形文字.这26个字母最初起源于埃及象形文字,后由腓尼基人改进发明了腓尼基字母, ...
- PPT文档页数显示的增加和更新
在PPT的右下角增加页数的显示能够帮助演讲者把握进度,所以会经常遇到需要把页数显示在右下角的情况,这次在制作ppt的时候也遇到了.因此在这里总结一下设置方法. 一.在右下角显示当前页数和总页数 1)获 ...
- window对象的inner/outer/page/screen详解
innerHeight : 返回窗口的文档显示区的高度,包含工具条与滚动条.说明:ie8以下不支持 outerHeight : 返回窗口的外部高度,包含工具条与滚动条.说明:ie8以下不支持 page ...
- bzoj2286 消耗战
还是虚树的题目啊... 如果只有一个询问,我们这么考虑,可以设dp[x]为只删除x子树内和x到父亲的边,使得x这棵子树内的能源岛屿都与x的父亲不连通的最小花费. 这样如果x本身是能源岛屿,那么dp[x ...
- QContester
发个福利好了(求不吐槽名字 自己做的软件,(目前)效果大概如上图- 对于我这种比较喜欢参加一些奇怪比赛的人来说还是有用的. 原理-就是在后台开七个浏览器2333 按左边的按钮会开始抓取比赛,进度可以在 ...