zoukankan      html  css  js  c++  java
  • [转]Spring的事务管理难点剖析(1):DAO和事务管理的牵绊

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

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

      JDBC访问数据库

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

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


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

    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.   
    10.     <context:property-placeholder location="classpath:jdbc.properties"/>  
    11.     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"  
    12.         destroy-method="close"   
    13.         p:driverClassName="${jdbc.driverClassName}"  
    14.         p:url="${jdbc.url}"   
    15.         p:username="${jdbc.username}"  
    16.         p:password="${jdbc.password}"/>  
    17.   
    18.     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"  
    19.           p:dataSource-ref="dataSource"/>  
    20. </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照样也可以工作,来看下面的例子:

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


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

    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.     …  
    10.     <bean id="sessionFactory"  
    11.           class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"  
    12.           p:dataSource-ref="dataSource">  
    13.         <property name="annotatedClasses">  
    14.             <list>  
    15.                 <value>com.baobaotao.User</value>  
    16.             </list>  
    17.         </property>  
    18.         <property name="hibernateProperties">  
    19.             <props>  
    20.                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>  
    21.                 <prop key="hibernate.show_sql">true</prop>  
    22.             </props>  
    23.         </property>  
    24.     </bean>  
    25.   
    26.     <bean id="hibernateTemplate"  
    27.           class="org.springframework.orm.hibernate3.HibernateTemplate"  
    28.           p:sessionFactory-ref="sessionFactory"/>  
    29.                   
    30. </beans>  


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

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


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

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

  • 相关阅读:
    Creating a generic Web Parts for hosting ASP.NET User Controls
    Speed Up SQL Server Apps 提高SQL Server应用程序的运行效率 (Part 1)
    How to use CreateChildContorls method inherited from System.Web.UI.Control
    How to quickly access Web Part Management Page
    SQL Script tips for MS SQL Server
    How to enable single signon service on the SPS
    A brief summary of UML & Rational Rose – Use Case Diagram, Part II
    Borland Together for Visual Studio.Net V2.0 安装问题
    Speed Up SQL Server Apps 提高SQL Server应用程序的运行效率 (Part 2)
    体验ReSharper V1.0 for VS.Net 2003 Part I
  • 原文地址:https://www.cnblogs.com/dirgo/p/5236855.html
Copyright © 2011-2022 走看看