Spring JPetStore学习(三)事务
spring配置文件application.xml中的事务总结
http://fluagen.blog.51cto.com/146595/148777
spring配置文件中几种配置事务的方式:
第一种:通过aop管理用户的增删改 (aspectJ)
<aop:config> <aop:advisor pointcut="execution(* *..OrderDao.*(..))" advice-ref="txAdvice" /> </aop:config> <tx:advice id="txAdvice"> <tx:attributes> <tx:method name="save*" /> <tx:method name="update*" /> <tx:method name="delete*" /> <tx:method name="*" read-only="true" /> </tx:attributes> </tx:advice>
第二种:通过拦截器Dao实现类实例
<bean name="dao" class="org.itfuture.[url]www.dao.impl.OrderDaoImpl[/url]"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> 事务bean <bean id="baseproxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="transactionManager"/> <property name="target" ref="dao"/>//所在拦截的目标指向 <property name="transactionAttributes">//拦截目标内的哪些方法 <props> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="select*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="query*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> 创建orderservice子类(实现类)的实例,注入 orderDao的实现类orderimpl的实例 <bean name="orderservice" class="org.itfuture.[url]www.service.impl.OrderServiceImpl[/url]"> <property name="dao" ref="baseproxy"></property>//引用baseproxy代理 </bean>
第三种配置:aop与interceptor相接合
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager">//引用transactionManager </property> <property name="transactionAttributes">//定义哪些方法是要用到事务的, <props> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="add*">PROPAGATION_REQUIRED</prop> <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> <bean id="auto" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> </list> </property> </bean>
第四种配置:个人认为比较好用这种
<bean id="dao" class="org.itfuture.[url]www.dao[/url]"> //把所有的*dao上升到接口 <property name="accountDao" ref="accountDao"/> <property name="categoryDao" ref="categoryDao"/> <property name="productDao" ref="productDao"/> <property name="itemDao" ref="itemDao"/> <property name="orderDao" ref="orderDao"/> </bean> <aop:config> <aop:advisor pointcut="execution(* *..interfaceDao.*(..))" advice-ref="txAdvice"/> //然后在拦截接口 </aop:config> <tx:advice id="txAdvice"> <tx:attributes> <tx:method name="insert*"/>//拦截接口中的以insert、update、update开头的所有方法 <tx:method name="update*"/> <tx:method name="*" read-only="true"/>//其它方法,只read-only </tx:attributes> </tx:advice>
Spring事务配置的五种方式
http://www.blogjava.net/robbie/archive/2009/04/05/264003.html
前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识。通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的。
总结如下:
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。
DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为 HibernateTransactionManager。
具体如下图:
根据代理机制的不同,总结了五种Spring事务的配置方式,配置文件如下:
第一种方式:每个Bean都有一个代理
<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml" /> <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" /> </bean> <!-- 定义事务管理器(声明式的事务) --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 配置DAO --> <bean id="userDaoTarget" class="com.bluesky.spring.dao.UserDaoImpl"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean id="userDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <!-- 配置事务管理器 --> <property name="transactionManager" ref="transactionManager" /> <property name="target" ref="userDaoTarget" /> <property name="proxyInterfaces" value="com.bluesky.spring.dao.GeneratorDao" /> <!-- 配置事务属性 --> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> </beans>
第二种方式:所有Bean共享一个代理基类
<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml" /> <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" /> </bean> <!-- 定义事务管理器(声明式的事务) --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean id="transactionBase" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init="true" abstract="true"> <!-- 配置事务管理器 --> <property name="transactionManager" ref="transactionManager" /> <!-- 配置事务属性 --> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <!-- 配置DAO --> <bean id="userDaoTarget" class="com.bluesky.spring.dao.UserDaoImpl"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean id="userDao" parent="transactionBase" > <property name="target" ref="userDaoTarget" /> </bean> </beans>
第三种方式:使用拦截器
<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml" /> <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" /> </bean> <!-- 定义事务管理器(声明式的事务) --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager" /> <!-- 配置事务属性 --> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <value>*Dao</value> </list> </property> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> </list> </property> </bean> <!-- 配置DAO --> <bean id="userDao" class="com.bluesky.spring.dao.UserDaoImpl"> <property name="sessionFactory" ref="sessionFactory" /> </bean> </beans>
第四种方式:使用tx标签配置的拦截器
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <context:annotation-config /> <context:component-scan base-package="com.bluesky" /> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml" /> <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" /> </bean> <!-- 定义事务管理器(声明式的事务) --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" propagation="REQUIRED" /> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="interceptorPointCuts" expression="execution(* com.bluesky.spring.dao.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="interceptorPointCuts" /> </aop:config> </beans>
第五种方式:全注解
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <context:annotation-config /> <context:component-scan base-package="com.bluesky" /> <tx:annotation-driven transaction-manager="transactionManager"/> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml" /> <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" /> </bean> <!-- 定义事务管理器(声明式的事务) --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> </beans>
此时在DAO上需加上@Transactional注解,如下:
package com.bluesky.spring.dao; import java.util.List; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import org.springframework.stereotype.Component; import com.bluesky.spring.domain.User; @Transactional @Component("userDao") public class UserDaoImpl extends HibernateDaoSupport implements UserDao { public List<User> listUsers() { return this.getSession().createQuery("from User").list(); } …… }
JPetStore的相关配置如下:
applicationContext.xml的部分如下:
<!-- ========================= ASPECT CONFIGURATION ======================== --> <aop:config> <!-- This definition creates auto-proxy infrastructure based on the given pointcut, expressed in AspectJ pointcut language. Here: applying the advice named "txAdvice" to all methods on classes named PetStoreImpl. --> <aop:advisor pointcut="execution(* *..PetStoreFacade.*(..))" advice-ref="txAdvice"/> <!-- This definition creates auto-proxy infrastructure based on the given pointcut, expressed in AspectJ pointcut language. Here: applying the advice named "emailAdvice" to insertOrder(Order) method of PetStoreImpl --> <!-- <aop:advisor pointcut="execution(* *..PetStoreFacade.insertOrder(*..Order))" advice-ref="emailAdvice"/> --> </aop:config> <!-- Transaction advice definition, based on method name patterns. Defaults to PROPAGATION_REQUIRED for all methods whose name starts with "insert" or "update", and to PROPAGATION_REQUIRED with read-only hint for all other methods. --> <tx:advice id="txAdvice"> <tx:attributes> <tx:method name="insert*"/> <tx:method name="update*"/> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice>
dataAccessContex-jta.xml如下
<?xml version="1.0" encoding="UTF-8"?> <!-- - Application context definition for JPetStore's data access layer. - Accessed by business layer objects defined in "applicationContext.xml" - (see web.xml's "contextConfigLocation"). - - This version of the data access layer works on two databases (main/order), - using JNDI DataSources with JtaTransactionManager. It obviously depends on - JTA support in the container, and on pre-configured container DataSources. - - This version also uses the "jndi:" namespace introduced in Spring 2.0 - to configured JNDI referenced objects. --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd"> <!-- ========================= RESOURCE DEFINITIONS ========================= --> <!-- Main JNDI DataSource for J2EE environments --> <!-- Refers to the main database, containing product and account data --> <!-- (see dataAccessContext-local.xml for an alternative) --> <jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/> <!-- Additional JNDI DataSource for J2EE environments --> <!-- Refers to the order database, containing order data --> <!-- (see dataAccessContext-local.xml for an alternative) --> <jee:jndi-lookup id="orderDataSource" jndi-name="jdbc/jpetstore-order"/> <!-- Transaction manager that delegates to JTA (for a transactional JNDI DataSource) --> <!-- Necessary here due to the need for distributed transactions across two databases --> <!-- (see dataAccessContext-local.xml for an alternative) --> <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/> <!-- SqlMap setup for iBATIS Database Layer --> <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation" value="WEB-INF/sql-map-config.xml"/> </bean> <!-- ========================= DAO DEFINITIONS: IBATIS IMPLEMENTATIONS ========================= --> <bean id="accountDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapAccountDao"> <property name="dataSource" ref="dataSource"/> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> <bean id="categoryDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapCategoryDao"> <property name="dataSource" ref="dataSource"/> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> <bean id="productDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapProductDao"> <property name="dataSource" ref="dataSource"/> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapItemDao"> <property name="dataSource" ref="dataSource"/> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> <!-- Refers to the order database here --> <!-- (see dataAccessContext-local.xml for an alternative) --> <bean id="orderDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapOrderDao"> <property name="dataSource" ref="orderDataSource"/> <property name="sqlMapClient" ref="sqlMapClient"/> <property name="sequenceDao" ref="sequenceDao"/> </bean> <!-- OrderDao definition for MS SQL Server --> <!-- (to be used instead of the default orderDao) --> <!-- <bean id="orderDao" class="org.springframework.samples.jpetstore.dao.ibatis.MsSqlOrderDao"> <property name="dataSource" ref="orderDataSource"/> <property name="sqlMapClient" ref="sqlMapClient"/> <property name="sequenceDao" ref="sequenceDao"/> </bean> --> <!-- Refers to the order database here --> <!-- (see dataAccessContext-local.xml for an alternative) --> <bean id="sequenceDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapSequenceDao"> <property name="dataSource" ref="orderDataSource"/> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> <!-- SequenceDao definition for Oracle databases --> <!-- (to be used instead of the default sequenceDao) --> <!-- <bean id="sequenceDao" class="org.springframework.samples.jpetstore.dao.ibatis.OracleSequenceDao"> <property name="dataSource" ref="orderDataSource"/> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> --> </beans>
dataAccessContex-local.xml如下
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <!-- - Application context definition for JPetStore's data access layer. - Accessed by business layer objects defined in "applicationContext.xml" - (see web.xml's "contextConfigLocation"). - - This version of the data access layer works on a combined database, - using a local DataSource with DataSourceTransactionManager. It does not - need any JTA support in the container: It will run as-is in plain Tomcat. --> <beans> <!-- ========================= RESOURCE DEFINITIONS ========================= --> <!-- Local Apache Commons DBCP DataSource that refers to a combined database --> <!-- (see dataAccessContext-jta.xml for an alternative) --> <!-- The placeholders are resolved from jdbc.properties through --> <!-- the PropertyPlaceholderConfigurer in applicationContext.xml --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- Transaction manager for a single JDBC DataSource --> <!-- (see dataAccessContext-jta.xml for an alternative) --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- SqlMap setup for iBATIS Database Layer --> <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation" value="WEB-INF/sql-map-config.xml"/> <property name="dataSource" ref="dataSource"/> </bean> <!-- ========================= DAO DEFINITIONS: IBATIS IMPLEMENTATIONS ========================= --> <bean id="accountDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapAccountDao"> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> <bean id="categoryDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapCategoryDao"> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> <bean id="productDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapProductDao"> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapItemDao"> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> <!-- Refers to the combined database here --> <!-- (see dataAccessContext-jta.xml for an alternative) --> <bean id="orderDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapOrderDao"> <property name="sqlMapClient" ref="sqlMapClient"/> <property name="sequenceDao" ref="sequenceDao"/> </bean> <!-- OrderDao definition for MS SQL Server --> <!-- (to be used instead of the default orderDao) --> <!-- <bean id="orderDao" class="org.springframework.samples.jpetstore.dao.ibatis.MsSqlOrderDao"> <property name="sqlMapClient" ref="sqlMapClient"/> <property name="sequenceDao" ref="sequenceDao"/> </bean> --> <!-- Refers to the combined database here --> <!-- (see dataAccessContext-jta.xml for an alternative) --> <bean id="sequenceDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapSequenceDao"> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> <!-- SequenceDao definition for Oracle databases --> <!-- (to be used instead of the default sequenceDao) --> <!-- <bean id="sequenceDao" class="org.springframework.samples.jpetstore.dao.ibatis.OracleSequenceDao"> <property name="sqlMapClient" ref="sqlMapClient"/> </bean> --> </beans>