原文地址:http://stamen.iteye.com/blog/1441758

有些人很少使用Spring而不使用Spring事务管理器的应用,因此常常有人会问:是否用了Spring,就一定要用Spring事务管理器,否则就无法进行数据的持久化操作呢?事务管理器和DAO是什么关系呢?
 
也许是DAO和事务管理如影随行的缘故吧,这个看似简单的问题实实在在地存在着,从初学者心中涌出,萦绕在老手的脑际。答案当然是否定的!我们都知道:事
务管理是保证数据操作的事务性(即原子性、一致性、隔离性、持久性,即所谓的ACID),脱离了事务性,DAO照样可以顺利地进行数据的操作。

  JDBC访问数据库

下面,我们来看一段使用Spring JDBC进行数据访问的代码:

  1. package com.baobaotao.withouttx.jdbc;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.jdbc.core.JdbcTemplate;
  4. import org.springframework.stereotype.Service;
  5. import org.springframework.context.ApplicationContext;
  6. import org.springframework.context.support.ClassPathXmlApplicationContext;
  7. import org.apache.commons.dbcp.BasicDataSource;
  8. @Service("userService")
  9. public class UserJdbcWithoutTransManagerService {
  10. @Autowired
  11. private JdbcTemplate jdbcTemplate;
  12. public void addScore(String userName,int toAdd){
  13. String sql = "UPDATE t_user u SET u.score = u.score + ? WHERE user_name =?";
  14. jdbcTemplate.update(sql,toAdd,userName);
  15. }
  16. public static void main(String[] args) {
  17. ApplicationContext ctx = new
  18. ClassPathXmlApplicationContext("com/baobaotao/withouttx/jdbc/jdbcWithoutTx.xml");
  19. UserJdbcWithoutTransManagerService service =
  20. (UserJdbcWithoutTransManagerService)ctx.getBean("userService");
  21. JdbcTemplate jdbcTemplate = (JdbcTemplate)ctx.getBean("jdbcTemplate");
  22. BasicDataSource basicDataSource = (BasicDataSource)jdbcTemplate.getDataSource();
  23. //①检查数据源autoCommit的设置
  24. System.out.println("autoCommit:"+ basicDataSource.getDefaultAutoCommit());
  25. //②插入一条记录,初始分数为10
  26. jdbcTemplate.execute("INSERT INTO t_user(user_name,password,score,last_logon_time)
  27. VALUES('tom','123456',10,"+System.currentTimeMillis()+")");
  28. //③调用工作在无事务环境下的服务类方法,将分数添加20分
  29. service.addScore("tom",20);
  30. //④查看此时用户的分数
  31. int score = jdbcTemplate.queryForInt(
  32. "SELECT score FROM t_user WHERE user_name ='tom'");
  33. System.out.println("score:"+score);
  34. jdbcTemplate.execute("DELETE FROM t_user WHERE user_name='tom'");
  35. }
  36. }

其中,jdbcWithoutTx.xml的配置文件如下所示:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:p="http://www.springframework.org/schema/p"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
  8. <context:component-scan base-package="com.baobaotao.withouttx.jdbc"/>
  9. <context:property-placeholder location="classpath:jdbc.properties"/>
  10. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
  11. destroy-method="close"
  12. p:driverClassName="${jdbc.driverClassName}"
  13. p:url="${jdbc.url}"
  14. p:username="${jdbc.username}"
  15. p:password="${jdbc.password}"/>
  16. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
  17. p:dataSource-ref="dataSource"/>
  18. </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照样也可以工作,来看下面的例子:

  1. package com.baobaotao.withouttx.hiber;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.core.io.ClassPathResource;
  4. import org.springframework.core.io.Resource;
  5. import org.springframework.jdbc.core.JdbcTemplate;
  6. import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
  7. import org.springframework.stereotype.Service;
  8. import org.springframework.context.ApplicationContext;
  9. import org.springframework.context.support.ClassPathXmlApplicationContext;
  10. import org.springframework.orm.hibernate3.HibernateTemplate;
  11. import org.apache.commons.dbcp.BasicDataSource;
  12. import org.springframework.test.jdbc.SimpleJdbcTestUtils;
  13. import com.baobaotao.User;
  14. @Service("hiberService")
  15. public class UserHibernateWithoutTransManagerService {
  16. @Autowired
  17. private HibernateTemplate hibernateTemplate;
  18. public void addScore(String userName,int toAdd){
  19. User user = hibernateTemplate.get(User.class,userName);
  20. user.setScore(user.getScore()+toAdd);
  21. hibernateTemplate.update(user);
  22. }
  23. public static void main(String[] args) {
  24. ApplicationContext ctx = new
  25. ClassPathXmlApplicationContext("com/baobaotao/withouttx/hiber/hiberWithoutTx.xml");
  26. UserHibernateWithoutTransManagerService service =
  27. (UserHibernateWithoutTransManagerService)ctx.getBean("hiberService");
  28. JdbcTemplate jdbcTemplate = (JdbcTemplate)ctx.getBean("jdbcTemplate");
  29. BasicDataSource basicDataSource = (BasicDataSource)jdbcTemplate.getDataSource();
  30. //①检查数据源autoCommit的设置
  31. System.out.println("autoCommit:"+ basicDataSource.getDefaultAutoCommit());
  32. //②插入一条记录,初始分数为10
  33. jdbcTemplate.execute("INSERT INTO t_user(user_name,password,score,last_logon_time)
  34. VALUES('tom','123456',10,"+System.currentTimeMillis()+")");
  35. //③调用工作在无事务环境下的服务类方法,将分数添加20分
  36. service.addScore("tom",20);
  37. //④查看此时用户的分数
  38. int score = jdbcTemplate.queryForInt(
  39. "SELECT score FROM t_user WHERE user_name ='tom'");
  40. System.out.println("score:"+score);
  41. jdbcTemplate.execute("DELETE FROM t_user WHERE user_name='tom'");
  42. }
  43. }

此时,采用hiberWithoutTx.xml的配置文件,其配置内容如下所示:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:p="http://www.springframework.org/schema/p"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
  8. <context:component-scan base-package="com.baobaotao.withouttx.hiber"/>
  9. <bean id="sessionFactory"
  10. class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
  11. p:dataSource-ref="dataSource">
  12. <property name="annotatedClasses">
  13. <list>
  14. <value>com.baobaotao.User</value>
  15. </list>
  16. </property>
  17. <property name="hibernateProperties">
  18. <props>
  19. <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
  20. <prop key="hibernate.show_sql">true</prop>
  21. </props>
  22. </property>
  23. </bean>
  24. <bean id="hibernateTemplate"
  25. class="org.springframework.orm.hibernate3.HibernateTemplate"
  26. p:sessionFactory-ref="sessionFactory"/>
  27. </beans>

com.baobaotao.User是使用了Hibernate注解的领域对象,代码如下所示:

  1. package com.baobaotao;
  2. import javax.persistence.Entity;
  3. import javax.persistence.Table;
  4. import javax.persistence.Column;
  5. import javax.persistence.Id;
  6. import java.lang.reflect.Field;
  7. import java.io.Serializable;
  8. @Entity
  9. @Table(name="T_USER")
  10. public class User implements Serializable{
  11. @Id
  12. @Column(name = "USER_NAME")
  13. private String userName;
  14. private String password;
  15. private int score;
  16. @Column(name = "LAST_LOGON_TIME")
  17. private long lastLogonTime = 0;
  18. }

运行UserHibernateWithoutTransManagerService,程序正确执行,并得到类似于
UserJdbcWithoutTransManagerService的执行结果。这说明Hibernate在Spring中,在没有事务管理器的情况
下,依然可以正常地进行数据的访问。

  注:以上内容摘自《Spring 3.x企业应用开发实战》

[转]Spring的事务管理难点剖析(1):DAO和事务管理的牵绊的更多相关文章

  1. Spring高级事务管理难点剖析

    1Spring事务传播行为 所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播.Spring支持7种事务传播行为 PROPAGATION_REQUIRED(加入已有事务) 如果当前没 ...

  2. Spring 事务管理高级应用难点剖析: 第 1 部分

    Spring 的事务管理是被使用得最多的功能之一,虽然 Spring 事务管理已经帮助程序员将要做的事情减到了最小.但在实际开发中,如果使用不当,依然会造成数据连接泄漏等问题.本系列以实际应用中所碰到 ...

  3. Spring 事务管理高级应用难点剖析--转

    第 1 部分 http://www.ibm.com/search/csass/search/?q=%E4%BA%8B%E5%8A%A1&sn=dw&lang=zh&cc=CN& ...

  4. Spring 事务管理高级应用难点剖析: 第 3 部分

    本文是“Spring 事务管理高级应用难点剖析” 系列文章的第 3 部分,作者将继续深入剖析在实际 Spring 事务管理应用中容易遇见的一些难点,包括在使用 Spring JDBC 时如果直接获取 ...

  5. Spring 事务管理高级应用难点剖析: 第 2 部分

    本文是“Spring 事务管理高级应用难点剖析” 系列文章的第 2 部分,作者将继续深入剖析在实际 Spring 事务管理应用中容易遇见的一些难点,包括混合使用多种数据访问技术(如 Spring JD ...

  6. Spring事务管理----声明式:利用TransactionProxyFactoryBean生成事务代理

    通常建议采用声明式事务管理.声明式事务管理的优势非常明显:代码中无需关于关注事务逻辑,让spring声明式事务管理负责事务逻辑,声明式事务管理无需与具体的事务逻辑耦合,可以方便地在不同事务逻辑之间切换 ...

  7. JTA事务管理--配置剖析(二)

    Spring引用Tomcat的 JTA事务     Tomcat是Servlet容器,但它提供了JNDI的实现,因此用户可以象在Java EE应用程序服务器中一样,在Tomcat中使用JNDI查找JD ...

  8. JTA事务管理--配置剖析

    概述    [IT168 专稿]Spring 通过AOP技术可以让我们在脱离EJB的情况下享受声明式事务的丰盛大餐,脱离Java EE应用服务器使用声明式事务的道路已经畅通无阻.但是很大部分人都还认为 ...

  9. Spring先进的交易管理困难剖析

    1Spring事务传播行为 所谓事务传播行为就是多个事务方法相互调用时,事务怎样在这些方法间传播.Spring支持7种事务传播行为 PROPAGATION_REQUIRED(增加已有事务) 假设当前没 ...

随机推荐

  1. ural 1208 Legendary Teams Contest

    题意描述:给定K支队伍,每队三个队员,不同队伍之间队员可能部分重复,输出这些队员同时能够组成多少完整的队伍: DFS,利用DFS深度优先搜索,如果该队所有队员都没有被访问过,那么将该队计入结果,再去选 ...

  2. 线程同步以及yield()、wait()、Notify()、Notifyall()

    一.线程同步 1.线程同步的目的是为了保护多个线程访问一个资源时对资源的破坏. 2.线程同步方法是通过锁来实现,每个对象都有切仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,其他访问该对 ...

  3. KSFramework:Unity3D开发框架快速入门

    KSFramework知识 https://github.com/mr-kelly/KSFramework KSFramework是一个整合KEngine.SLua和一些开发组件组成的全功能Unity ...

  4. java函数参数默认值

    java函数参数默认值 今天,需要设定java函数参数的默认值,发现按照其它语言中的方法行不通 java中似乎只能通过函数的重载来实现 函数参数默认代码

  5. JavaWeb学习总结,文件上传和下载

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  6. [No000037]操作系统Operating Systems操作系统历史与硬件概况History of OS & Summaries!

    培根:读史使人明智 操作系统的简史 (1955-1965) 计算机非常昂贵,上古神机IBM7094 ,造价在250万美元以上 计算机使用原则:只专注于计算 批处理操作系统(Batch system) ...

  7. [No00002C]人的寿命应该能达到100至175岁-北大齐教授健康讲座笔录

      人的寿命应该能达到100 至175 岁,为什么都没有达到呢?最主要一个原因就是我们不重视保健,不懂得保健的知识.很多人死于无知,这很冤枉啊! 大家知道怎么保健吗?国际上有个维多利亚宣言,宣言里有三 ...

  8. 转: 使用Eclipse的Working Set,界面清爽多了

    from: http://iyuanbo.iteye.com/blog/1158136 使用Eclipse的Working Set,界面清爽多了   想必大家的Eclipse里也会有这么多得工程... ...

  9. mvc5权限管理(简单登录):ActionFilterAttribute

    效果图: 1.控制器 public ActionResult Index() { return View(); } [HttpPost] public ActionResult Index(User ...

  10. Oracle中把一个DateTime的字符串转化成date类型。to_date('2016/12/8 18:55:43','yyyy/MM/dd hh24:mi:ss'),

    Oracle中把一个DateTime或者该形态字符串转化成date类型. to_date('2016/12/8 18:55:43','yyyy/MM/dd hh24:mi:ss'), 或者: sele ...