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企业应用开发实战》

  • 相关阅读:
    C#中WinForm程序退出方法技巧(转载)
    webbrowser访问网站禁止弹窗
    (转载)ASP.NET三大核心对象及基础功能解析
    webBrowser调用外部js文件和js函数(转载)
    java IO流
    java线程状态,优先级
    java线程
    Collection接口,Map接口
    序列化和反序列化
    JsonUtil自定义
  • 原文地址:https://www.cnblogs.com/dirgo/p/5236855.html
Copyright © 2011-2022 走看看