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自动创建事务代理。