Spring中的事务处理(下)

来源:互联网 发布:mac怎么复制 编辑:程序博客网 时间:2024/06/10 15:11

上篇《Spring中的事务处理(上)》讲了SpringJDBC管理事务的方式,也说了Spring支持的事务管理器的类型,这篇主要列举下当持久层为Hibernate时,Spring所支持的几种配置事务的方式,先说两种配置sessionFactory(数据源)的方式。

第一种,为直接读取hibernate.cfg.xml文件获取连接数据库信息的方式,hibernate.cfg.xml配置如下:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"><hibernate-configuration>    <session-factory>        <property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>        <property name="hibernate.connection.password">1</property>        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/ssh2</property>        <property name="hibernate.connection.username">root</property>        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>        <property name="hibernate.hbm2ddl.auto">update</property>                <!--         packagesToScan属性解决此类问题        <mapping class="com.tgb.entity.User"/>         -->    </session-factory></hibernate-configuration>

spring配置文件applicationContext-common.xml中的配置如下:

<!-- 第一种配置方法,定义一个与数据库的连接 --><bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"><property name="configLocation"><value>classpath:hibernate/hibernate.cfg.xml</value></property><property name="packagesToScan"><value>com.tgb.entity</value></property></bean>

Hibernate中实体类的映射文件越来越多时,可以采用packagesToScan属性,扫描某一个包下所有符合条件的*.hbm.xml文件,免去了在hibernate.cfg.xml配置大量映射文件所带来的不便。

第二种方式是直接在Spring配置文件applicationContext-common.xml中配置数据源,不再读取hibernate.cfg.xml,配置如下:

 <!-- 第二种配置方法 -->  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="org.gjt.mm.mysql.Driver"></property> <property name="password" value="1"></property> <property name="url" value="jdbc:mysql://localhost:3306/ssh2"></property> <property name="username" value="root"></property> </bean><bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"><property name="dataSource" ref="dataSource"></property><property name="hibernateProperties"><props><prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop><prop key="hibernate.hbm2ddl.auto">update</prop><prop key="hibernate.show_sql">true</prop></props></property><property name="mappingLocations"><list><value>classpath:/com/tgb/entity/User.hbm.xml</value></list></property></bean> 

以上是两种配置HibernatesessionFactory的方式,可自由选择,下面是Spring针对Hibernate事务管理器的四种配置方法,推荐第一种方式。

首先定义一个事务管理器:

 <!--配置一个事务管理器,spring内置多个管理器实现方式,aop中他充当的是Aspect(切面)  --><bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory"/></bean>

一.    <tx/>标签来定义事务方式,<aop/>标签来关联对应的方法上:

<!-- 配置一个aspect事务管理器,spring内置多个管理器实现方式,其中mybatis利用下类完成事务管理 --><bean id="transManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" value="datasource"></property></bean><!-- 配置advice(通知),Joinpoint(连接点),以及事务的传播行为和隔离级别--><tx:advice id="transactionAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="query*" isolation="DEFAULT" propagation="REQUIRED" read-only="true"/><tx:method name="insert*" isolation="DEFAULT" propagation="REQUIRED" rollback-for="Exception"/><tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED" no-rollback-for="myException"/><tx:method name="del*" isolation="DEFAULT" propagation="REQUIRED"/><tx:method name="*" isolation="DEFAULT" propagation="REQUIRED"/></tx:attributes></tx:advice><!--配置pointcut(切入点)以及需要通知的advisor(通知者)  --><aop:config><aop:pointcut id="transactionPoincut" expression="execution(* com.icloudmark.smsfs.service.*.*(..))" /><aop:advisor advice-ref="transactionAdvice" pointcut-ref="transactionPoincut"/></aop:config>


在默认情况下,Spring采用JDK代理,如想用cgLib代理,需引入相应的Jar包,然后按照上面注释部分,将proxy-target-class属性设置为true,其余不变。

二.   利用TransactionProxyFactoryBean配置事务,下面为配置方式:

 <!-- 第二种配置事务的方式,代理 <span style="font-family: Arial, Helvetica, sans-serif;">  --> </span> <bean id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> <property name="proxyTargetClass" value="true"></property> 采用cglib代理方式 <property name="transactionManager" ref="transactionManager"></property> <property name="transactionAttributes"> <props> <prop key="add*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="modify*">PROPAGATION_REQUIRED,+myException</prop> <prop key="del*">PROPAGATION_REQUIRED</prop> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <bean id="userDao" parent="transactionProxy"> <property name="target" ref="iUserDao"></property> </bean>

     这种方式值得注意的地方是,必须要将注入的bean对象和事务代理对象关联起来,iUserDao为实际配置的bean对象。如下:

<!-- 为第二种事务配置方式单独配置一个bean,或者在application-common.xml中采用内联式配置 --><bean id="iUserDao" class="com.tgb.dao.UserDao2"><property name="sessionFactory" ref="sessionFactory"/></bean>

这种方式一般用在2.0版本,下面是Spring官方对他的一个说明:

Proxy factory bean for simplified declarative transaction handling. This is a convenient alternative to a standard AOP ProxyFactoryBean with a separate TransactionInterceptor definition.

HISTORICAL NOTE: This class was originally designed to cover the typical case of declarative transaction demarcation: namely, wrapping a singleton target object with a transactional proxy, proxying all the interfaces that the target implements. However, in Spring versions 2.0 and beyond, the functionality provided here is superseded by the more convenient tx: XML namespace. See the declarative transaction management section of the Spring reference documentation to understand the modern options for managing transactions in Spring applications. For these reasons, users should favor of the tx: XML namespace as well as the @Transactional and @EnableTransactionManagement annotations.

    用拦截器的方式,这也是一种较为底层古老的配置方式,如下:

  <!-- 第三种配置事务的方式,拦截器 -->  <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">  <property name="transactionManager" ref="transactionManager"></property> <property name="transactionAttributes"> <props> <prop key="add*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="modify*">PROPAGATION_REQUIRED,+myException</prop> <prop key="del*">PROPAGATION_REQUIRED</prop> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property>    </bean>  <bean id="proxyFactory" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">  <property name="interceptorNames">  <list><value>transactionInterceptor</value>  </list>  </property>  <property name="beanNames">  <list>  <value>*Dao</value>  </list>  </property>  </bean>

beanNames属性可以匹配所有符合条件的对象。

四.    用注解的方式,这种方式一般不建议使用。需要配置的如下:

   <!-- 第四种配置事务的方式,注解 -->   <tx:annotation-driven transaction-manager="transactionManager"/>

需要注意配置<context:annotation-config/>开启Annotation注解。下面是需要加入事务的类:

package com.tgb.dao;import org.springframework.orm.hibernate3.HibernateTemplate;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import com.tgb.entity.User;import com.tgb.exception.MyException;@Transactional(propagation=Propagation.REQUIRED)public class UserDaoImpl extends HibernateTemplate implements UserDao {@Override@Transactional(propagation=Propagation.REQUIRED,rollbackForClassName="Exception")public void addUser(User user) {this.save(user);throw new RuntimeException();}@Override@Transactional(propagation=Propagation.REQUIRED,noRollbackForClassName="com.tgb.exception.MyException")public void modifyUser(User user) {this.update(user);throw new MyException();}@Override@Transactional(propagation=Propagation.REQUIRED,rollbackForClassName="Exception")public void delUser(String username) {this.delete(this.load(User.class, username));}}

     事务是企业应用开发的重要组成部分,他使软件更加可靠。他们确保一种要么全有要么全无的行为,防止数据不一致而导致的不可预测的错误发生。他们同事也支持并发,防止并发应用线程在操作同一数据互相影响。

   推荐一篇事务的文章:http://wenku.baidu.com/link?url=ZnDgWQb9b6pRYar47AyIyrRJ7ZE6OzMF6G_vGc6SdOkkp6QsWZSoyVn0vJJQZTehb7Z1-MnRexK0TYOp3D-lEy0Ow24i7KB3JMlIEQSHeou

原创粉丝点击