spring、hibernate调整3(事务)

spring、hibernate整合3(事务)

声明式事务管理的配置方式通常有如下四种。
•使用TransactionProxyFactoryBean 为目标bean 生成事务代理的配置。此方式最传统,但配置文件膝肿,难以阅读。
•采用bean 继承的事务代理配置方式比较简沽,但依然是增量式配置。
•使用BeanNameAutoProxyCreator ,根据bean name 自动生成事务代理的方式,这是直接利用Spring 的AOP 框架配置事务代理的方式,需要对Spring 的AOP 框架有所理解,但这种方式避免了增量式配置,效果非常不错。
• DefaultAdvisorAutoProxyCreator: 这也是直接利用Spring 的AOP 框架配置事务代理的方式,效果也非常不错,只是这种配置方式的可读性不如第三种方式。

 

 

 

1、TransactionProxyFactoryBean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>org.gjt.mm.mysql.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://192.168.0.80:3306/orders</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>1234</value>
		</property>
	</bean>

	<!-- 定义hibernate的SessionFactory -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<!-- 所有的PO映射文件 -->
		<property name="mappingResources">
			<list>
				<value>com/oracle/Student.hbm.xml</value>
			</list>
		</property>

		<!-- 定义hibernate的SessionFactory的属性 -->
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.MySQLDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="current_session_context_class">thread</prop>
				<prop key="hibernate.cache.provider_class">
					org.hibernate.cache.EhCacheProvider
				</prop>
				<prop key="connection.pool_size">10</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>

		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
	</bean>

	<!-- 定义事务管理器,适用于Hibernte 的事务管理器 -->
	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<!--需要注入一个SessionFactory-->
		<property name="sessionFactory">
			<ref local="sessionFactory" />
		</property>
	</bean>
	

	<!-- 定义DAO Bean ,作为事务代理的目标 -->
	<bean id="personDaoTarget" class="lee.PersonDaoHibernate">
		<!-- 注入SessionFactory引用 -->
		<property name="sessionFactory">
			<ref local="sessionFactory" />
		</property>
	</bean>

	<!-- 定义DAO bean 的事务代理 -->
	<bean id="personDao"
		class="org.spr工ngframework.transaction.interceptor.TransactionProxyFactoryBean">
		<!-- 注入事务管理器 -->
		<property name="transactionManager">
			<ref bean="transactionManager" />
		</property>
		<!-- 设置事务属性 -->
		<property name="transactionAttributes">
			<props>
				<!-- 全部以find打头的方法,采用required事务策略,并且只读 -->
				<prop key="find*">PROPAGATION_REQU工RED , readOnly</prop>
				<!--  其他方法,采用required事务策略 -->
				<prop key="*">PROPAGATION_REQUIRED</prop>
			</props>
		</property>
		<!-- 为事务代理bean 设置目标bean  -->
		<property name="target">
			<ref local="personDaoTarget" />
		</property>
	</bean>
</beans>

 目标bean 直接暴露在Spring 容器中,可以直接引用,如果目标bean 被误引用,将导致业务操作不具备事务性。为了避免这种现象,可将目标bean 配置成嵌套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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>org.gjt.mm.mysql.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://192.168.0.80:3306/orders</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>1234</value>
		</property>
	</bean>

	<!-- 定义hibernate的SessionFactory -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<!-- 所有的PO映射文件 -->
		<property name="mappingResources">
			<list>
				<value>com/oracle/Student.hbm.xml</value>
			</list>
		</property>

		<!-- 定义hibernate的SessionFactory的属性 -->
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.MySQLDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="current_session_context_class">thread</prop>
				<prop key="hibernate.cache.provider_class">
					org.hibernate.cache.EhCacheProvider
				</prop>
				<prop key="connection.pool_size">10</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>

		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
	</bean>

	<!-- 定义事务管理器,适用于Hibernte 的事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<!--需要注入一个SessionFactory-->
		<property name="sessionFactory">
			<ref local="sessionFactory" />
		</property>
	</bean>




	<!-- 定义DAO bean 的事务代理 -->
	<bean id="personDao"
		class="org.spr工ngframework.transaction.interceptor.TransactionProxyFactoryBean">
		<!-- 注入事务管理器 -->
		<property name="transactionManager">
			<ref bean="transactionManager" />
		</property>
		<!-- 设置事务属性 -->
		<property name="transactionAttributes">
			<props>
				<!-- 全部以find打头的方法,采用required事务策略,并且只读 -->
				<prop key="find*">PROPAGATION_REQU工RED , readOnly</prop>
				<!--  其他方法,采用required事务策略 -->
				<prop key="*">PROPAGATION_REQUIRED</prop>
			</props>
		</property>
		<!-- 为事务代理bean 设置目标bean  -->
		<property name="target">
			<!-- 定义DAO Bean ,作为事务代理的目标 -->
			<bean class="lee.PersonDaoHibernate">
				<!-- 注入SessionFactory引用 -->
				<property name="sessionFactory">
					<ref local="sessionFactory" />
				</property>
			</bean>
		</property>
	</bean>
</beans>
 

2、采用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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>org.gjt.mm.mysql.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://192.168.0.80:3306/orders</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>1234</value>
		</property>
	</bean>

	<!-- 定义hibernate的SessionFactory -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<!-- 所有的PO映射文件 -->
		<property name="mappingResources">
			<list>
				<value>com/oracle/Student.hbm.xml</value>
			</list>
		</property>

		<!-- 定义hibernate的SessionFactory的属性 -->
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.MySQLDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="current_session_context_class">thread</prop>
				<prop key="hibernate.cache.provider_class">
					org.hibernate.cache.EhCacheProvider
				</prop>
				<prop key="connection.pool_size">10</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>

		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
	</bean>

	<!-- 定义事务管理器,适用于Hibernte 的事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<!--需要注入一个SessionFactory-->
		<property name="sessionFactory">
			<ref local="sessionFactory" />
		</property>
	</bean>

	<!-- 定义抽象bean,作为模板,供使用 -->
	<bean id="txBase"
		class="org.spr工ngframework.transaction.interceptor.TransactionProxyFactoryBean"
		abstract="true">
		<property name="transactionManager">
			<ref bean="transactionManager" />
		</property>
		<!-- 设置事务属性 -->
		<property name="transactionAttributes">
			<props>
				<!-- 全部以find打头的方法,采用required事务策略,并且只读 -->
				<prop key="find*">PROPAGATION_REQU工RED , readOnly</prop>
				<!--  其他方法,采用required事务策略 -->
				<prop key="*">PROPAGATION_REQUIRED</prop>
			</props>
		</property>
	</bean>


	<!-- 定义DAO bean 的事务代理 -->
	<bean id="personDao" parent="txBase">
		<property name="target">
			<bean class="lee.PersonDaoHibernate">
				<property name="sessionFactory">
					<ref local="sessionFactory" />
				</property>
			</bean>
		</property>
	</bean>
</beans>
 

3、BeanNameAutoProxyCreator拦截器

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>org.gjt.mm.mysql.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://192.168.0.80:3306/orders</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>1234</value>
		</property>
	</bean>

	<!-- 定义hibernate的SessionFactory -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<!-- 所有的PO映射文件 -->
		<property name="mappingResources">
			<list>
				<value>com/oracle/Student.hbm.xml</value>
			</list>
		</property>

		<!-- 定义hibernate的SessionFactory的属性 -->
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.MySQLDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="current_session_context_class">thread</prop>
				<prop key="hibernate.cache.provider_class">
					org.hibernate.cache.EhCacheProvider
				</prop>
				<prop key="connection.pool_size">10</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>

		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
	</bean>

	<!-- 定义事务管理器,适用于Hibernte 的事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<!--需要注入一个SessionFactory-->
		<property name="sessionFactory">
			<ref local="sessionFactory" />
		</property>
	</bean>


	<!-- 配置事务拦截器-->
	<bean id="transactionInterceptor"
		class="org.springfrarnework.transaction.interceptor.TransactionInterceptor">
		<!-- 事务拦截器bean 需要依赖注入一个事务管理器-->
		<property name="transactionManager" ref="transactionManager" />
		<property name="transactionAttributes">
			<!-- 下面定义事务传播属性-->
			<props>
				<prop key="insert*">PROPAGATION_REQIURED</prop>
				<prop key="find*">PROPAGATION_REQUIRED , readOnly</prop>
				<prop key="*">PROPAGAT工ON_REQUIRED</prop>
			</props>
		</property>
	</bean>
	<!--
		定义BeanNameAutoProxyCreator ,该bean 是个bean 后处理器,无须被引用,因此没有id 属性这个bean
		后处理器,根据事务拦截器为目标bean 自动创建事务代理
	-->
	<bean
		class="org.spr工ngframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
		<!-- 指定对满足哪些bean name 的bean 自动生成业务代理 -->
		<property name="beanNames">
			<!-- 下面是所有需要自动创建事务代理的bean-->
			<list>
				<value>personDao</value>
			</list>
			<!--此处可增加其他需要自动创建事务代理的bean-->
		</property>
		<!-- 下面定义BeanNameAutoProxyCreator所需的事务拦截器 -->
		<property name="InterceptorNames">
			<list>
				<value>transactionlnterceptor</value>
				<!-- 此处可增加其他新的interceptor -->
			</list>
		</property>
	</bean>
	<!--定义DAO Bean ,由于BeanNameAutoProxyCreator自动生成事务代-->
	<bean id="personDao" class="lee.PersonDaoHibernate">
		<property name="sess工onFactory">
			<ref local="sessionFactory" />
		</property>
	</bean>
</beans>
 

4、用DefaultAdvisorAutoProxyCreator自动创建事务代理

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>org.gjt.mm.mysql.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://192.168.0.80:3306/orders</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password">
			<value>1234</value>
		</property>
	</bean>

	<!-- 定义hibernate的SessionFactory -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<!-- 所有的PO映射文件 -->
		<property name="mappingResources">
			<list>
				<value>com/oracle/Student.hbm.xml</value>
			</list>
		</property>

		<!-- 定义hibernate的SessionFactory的属性 -->
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.MySQLDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="current_session_context_class">thread</prop>
				<prop key="hibernate.cache.provider_class">
					org.hibernate.cache.EhCacheProvider
				</prop>
				<prop key="connection.pool_size">10</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>

		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
	</bean>

	<!-- 定义事务管理器,适用于Hibernte 的事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<!--需要注入一个SessionFactory-->
		<property name="sessionFactory">
			<ref local="sessionFactory" />
		</property>
	</bean>


	<!-- 配置事务拦截器-->
	<bean id="transactionInterceptor"
		class="org.springfrarnework.transaction.interceptor.TransactionInterceptor">
		<!-- 事务拦截器bean 需要依赖注入一个事务管理器-->
		<property name="transactionManager" ref="transactionManager" />
		<property name="transactionAttributes">
			<!-- 下面定义事务传播属性-->
			<props>
				<prop key="insert*">PROPAGATION_REQIURED</prop>
				<prop key="find*">PROPAGATION_REQUIRED , readOnly</prop>
				<prop key="*">PROPAGAT工ON_REQUIRED</prop>
			</props>
		</property>
	</bean>


	<!--定义事务Advisor-->
	<bean
		class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
		<!-- 定义advisor 时,必须传入Interceptor-->
		<property name="transactionInterceptor" ref="transactionInterceptor" />
	</bean>

	<!-- DefaultAdvisorAutoProxyCreator搜索容器中的advisor,并为每个bean 创建代理 -->
	<bean
		class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
	<!--定义DAO Bean ,由于BeanNameAutoProxyCreator自动生成事务代理-->
	<bean id="personDao" class="lee.PersonDaoHibernate">
		<property name="sessionFactory">
			<ref local="sessionFactory" />
		</property>
	</bean>
</beans>
 

 

 

 

 

总结:

(1)Transaction ProxyFactoryBean最原始,事务代理的配置依然是增量式的,每个事务代理都需要单独配置。

(2)Transaction ProxyFactoryBean使用继承后简化了配置,事务代理的配置依然是增量式的,每个事务代理都需要单独配置。

(3)BeanNameAutoProxyCreator 自动创建事务代理,可避免增量式配置,者使用事务拦截器创建代,一种直观。

(4)DefaultAdvisorAutoProxyCreator自动创建事务代理,可避免增量式配置,使用Advisor 创建事务代理,更加简洁。

推荐使用BeanNameAutoProxyCreator 自动创建事务代理或者DefaultAdvisorAutoProxyCreator自动创建事务代理。