尝试在代码中动态切换spring的事务策略

用过spring的人都熟悉spring的事务管理机制,并且spring支持jta分布式事务,那么,我一直在想,能否在代码中动态的切换事务类型呢?如果当前要操作的多个表在同一个数据源上,就直接本地

事务好了,如果当前操作的表分别在不同的数据源上,就切换成spring里配置好的jta事务。也就是说,事务还是用spring的声明式事务,但是用代码手动的选取用哪一个,能不能这样呢??
    我做了个测试,在测试中,配置了两个spring配置文件,一个是使用本地事务,并且只有一个数据源,另一个是jta事务,并且有两个数据源,它们分别如下:

applicationContext-sys.xml(使用本地事务,并且只有一个数据源)

Java代码 复制代码  收藏代码
  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" xmlns:aop="http://www.springframework.org/schema/aop"  
  4.     xmlns:tx="http://www.springframework.org/schema/tx"  
  5.     xsi:schemaLocation="  
  6.     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
  7.     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd  
  8.     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
  9.   
  10.     <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  11.         <property name="locations">  
  12.             <list>  
  13.                 <value>classpath*:conf/jdbc.properties</value>  
  14.             </list>  
  15.         </property>  
  16.     </bean>  
  17.   
  18.     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">  
  19.         <property name="driverClassName" value="${driverClassName}" />  
  20.         <property name="url" value="${url}" />  
  21.         <property name="username" value="${username}" />  
  22.         <property name="password" value="${password}" />  
  23.     </bean>  
  24.     <bean id="sessionFactory"  
  25.         class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
  26.         <property name="dataSource" ref="dataSource" />  
  27.         <property name="hibernateProperties">  
  28.             <props>  
  29.                 <prop key="hibernate.dialect">  
  30.                     ${dialect}  
  31.                 </prop>  
  32.                 <prop key="hibernate.default_batch_fetch_size">10</prop>  
  33.                 <prop key="hibernate.max_fetch_depth">0</prop>  
  34.                 <prop key="hibernate.show_sql">${show_sql}</prop>  
  35.             </props>  
  36.         </property>  
  37.         <property name="mappingDirectoryLocations">  
  38.             <list>  
  39.                 <value>classpath*:/com/zhangweilin/po/</value>  
  40.             </list>  
  41.         </property>  
  42.     </bean>  
  43.   
  44.     <bean id="txManager"  
  45.         class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  46.         <property name="sessionFactory" ref="sessionFactory" />  
  47.         <property name="nestedTransactionAllowed" value="true" />  
  48.     </bean>  
  49.   
  50.     <tx:annotation-driven transaction-manager="txManager" />  
  51.   
  52.     <aop:config>  
  53.         <aop:pointcut id="commonServiceOperation"  
  54.             expression="execution(* com.zhangweilin.service.*Service.*(..))" />  
  55.         <aop:advisor pointcut-ref="commonServiceOperation"  
  56.             advice-ref="txAdvice" />  
  57.     </aop:config>  
  58.   
  59.     <tx:advice id="txAdvice" transaction-manager="txManager">  
  60.         <tx:attributes>  
  61.             <tx:method name="init*" rollback-for="Exception" />  
  62.             <tx:method name="save*" rollback-for="Exception" />  
  63.             <tx:method name="create*" rollback-for="Exception" />  
  64.             <tx:method name="login*" rollback-for="Exception" />  
  65.             <tx:method name="add*" rollback-for="Exception" />  
  66.             <tx:method name="update*" rollback-for="Exception" />  
  67.             <tx:method name="modify*" rollback-for="Exception" />  
  68.             <tx:method name="delete*" rollback-for="Exception" />  
  69.             <tx:method name="remove*" rollback-for="Exception" />  
  70.             <tx:method name="clear*" rollback-for="Exception" />  
  71.             <tx:method name="register*" rollback-for="Exception" />  
  72.             <tx:method name="*" read-only="true" />  
  73.         </tx:attributes>  
  74.     </tx:advice>  
  75.       
  76.     <!--   
  77.     <bean id="ehcacheManager"  
  78.         class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">  
  79.         <property name="configLocation" value="/WEB-INF/classes/ehcache.xml" />  
  80.     </bean>  
  81.      -->  
  82.           
  83.     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">  
  84.         <property name="dataSource" ref="dataSource"/>  
  85.     </bean>  
  86.       
  87.           
  88.     <bean id="dao" class="com.zhangweilin.core.DaoImpl">  
  89.         <property name="sessionFactory" ref="sessionFactory" />  
  90.         <property name="jdbcTemplate" ref="jdbcTemplate" />  
  91.     </bean>   
  92. </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: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.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

	<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath*:conf/jdbc.properties</value>
			</list>
		</property>
	</bean>

	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="${driverClassName}" />
		<property name="url" value="${url}" />
		<property name="username" value="${username}" />
		<property name="password" value="${password}" />
	</bean>
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					${dialect}
				</prop>
				<prop key="hibernate.default_batch_fetch_size">10</prop>
				<prop key="hibernate.max_fetch_depth">0</prop>
				<prop key="hibernate.show_sql">${show_sql}</prop>
			</props>
		</property>
		<property name="mappingDirectoryLocations">
			<list>
				<value>classpath*:/com/zhangweilin/po/</value>
			</list>
		</property>
	</bean>

	<bean id="txManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
		<property name="nestedTransactionAllowed" value="true" />
	</bean>

	<tx:annotation-driven transaction-manager="txManager" />

	<aop:config>
		<aop:pointcut id="commonServiceOperation"
			expression="execution(* com.zhangweilin.service.*Service.*(..))" />
		<aop:advisor pointcut-ref="commonServiceOperation"
			advice-ref="txAdvice" />
	</aop:config>

	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="init*" rollback-for="Exception" />
			<tx:method name="save*" rollback-for="Exception" />
			<tx:method name="create*" rollback-for="Exception" />
			<tx:method name="login*" rollback-for="Exception" />
			<tx:method name="add*" rollback-for="Exception" />
			<tx:method name="update*" rollback-for="Exception" />
			<tx:method name="modify*" rollback-for="Exception" />
			<tx:method name="delete*" rollback-for="Exception" />
			<tx:method name="remove*" rollback-for="Exception" />
			<tx:method name="clear*" rollback-for="Exception" />
			<tx:method name="register*" rollback-for="Exception" />
			<tx:method name="*" read-only="true" />
		</tx:attributes>
	</tx:advice>
	
	<!-- 
	<bean id="ehcacheManager"
		class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
		<property name="configLocation" value="/WEB-INF/classes/ehcache.xml" />
	</bean>
	 -->
		
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    	<property name="dataSource" ref="dataSource"/>
	</bean>
	
		
	<bean id="dao" class="com.zhangweilin.core.DaoImpl">
		<property name="sessionFactory" ref="sessionFactory" />
		<property name="jdbcTemplate" ref="jdbcTemplate" />
	</bean> 
</beans>




另一个:applicationContext-test-jotm.xml(jta事务,并且有两个数据源)


Java代码 复制代码  收藏代码
  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" xmlns:aop="http://www.springframework.org/schema/aop"  
  4.     xmlns:tx="http://www.springframework.org/schema/tx"  
  5.     xsi:schemaLocation="  
  6.     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
  7.     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd  
  8.     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">  
  9.   
  10. <!-- jotm配置 -->  
  11.     <bean id="mysqldatasource" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource">    
  12.         <property name="dataSource">  
  13.         <!--内部XA数据源  -->  
  14.             <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">    
  15.                 <property name="transactionManager" ref="jotm" />    
  16.                 <property name="driverName" value="com.mysql.jdbc.Driver" />    
  17.                 <property name="url" value="jdbc:mysql://172.16.18.75:3306/?useUnicode=true&amp;characterEncoding=UTF-8" />    
  18.             </bean>    
  19.         </property>    
  20.         <property name="user" value="root" />    
  21.         <property name="password" value="123456" />    
  22.     </bean>    
  23.     
  24.     
  25.     <bean id="h2datasource" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource">    
  26.         <property name="dataSource">  
  27.          <!--内部XA数据源    -->  
  28.             <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">    
  29.                 <property name="transactionManager" ref="jotm" />    
  30.                 <property name="driverName" value="com.mysql.jdbc.Driver" />    
  31.                 <property name="url" value="jdbc:mysql://localhost:3306/pay?useUnicode=true&amp;characterEncoding=UTF-8" />    
  32.             </bean>    
  33.         </property>    
  34.         <property name="user" value="zwllxs" />    
  35.         <property name="password" value="123456" />    
  36.     </bean>    
  37.       
  38.     <bean id="sessionFactory1" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">    
  39.         <property name="dataSource" ref="mysqldatasource"/>    
  40.         <property name="mappingDirectoryLocations">  
  41.             <list>  
  42.                 <value>classpath*:/com/zhangweilin/po/</value>  
  43.             </list>  
  44.         </property>  
  45.         <property name="hibernateProperties">    
  46.             <props>    
  47.                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>    
  48.                 <prop key="hibernate.show_sql">true</prop>    
  49.                 <prop key="hibernate.jdbc.batch_size">50</prop>    
  50.                 <prop key="hibernate.cache.use_query_cache">true</prop>    
  51.                 <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>    
  52.             </props>    
  53.         </property>    
  54.         <!--   
  55.             <property name="jtaTransactionManager">    
  56.                 <ref bean="jotm" />    
  57.             </property>  
  58.          -->    
  59.     </bean>    
  60.       
  61.      <bean id="sessionFactory2" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">    
  62.             <property name="dataSource" ref="h2datasource"/>    
  63.             <property name="mappingDirectoryLocations">  
  64.                 <list>  
  65.                     <value>classpath*:/com/zhangweilin/po/</value>  
  66.                 </list>  
  67.             </property>  
  68.             <property name="hibernateProperties">    
  69.                 <props>    
  70.                     <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>    
  71.                     <prop key="hibernate.show_sql">true</prop>    
  72.                     <prop key="hibernate.jdbc.batch_size">50</prop>    
  73.                     <prop key="hibernate.cache.use_query_cache">true</prop>    
  74.                     <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>    
  75.                 </props>    
  76.             </property>    
  77.              <!--   
  78.                 <property name="jtaTransactionManager">    
  79.                     <ref bean="jotm" />    
  80.                 </property>  
  81.              -->    
  82.     </bean>    
  83.       
  84.           
  85.     <bean id="dao1" class="com.zhangweilin.core.DaoImpl">  
  86.         <property name="sessionFactory" ref="sessionFactory1" />  
  87.     </bean>   
  88.           
  89.     <bean id="dao2" class="com.zhangweilin.core.DaoImpl">  
  90.         <property name="sessionFactory" ref="sessionFactory2" />  
  91.     </bean>   
  92.       
  93.     <bean id="loginLogService2" class="com.zhangweilin.service.impl.LoginLogServiceImpl">  
  94.         <property name="dao" ref="dao1" />  
  95.     </bean>  
  96.           
  97.     <bean id="articleService2" class="com.zhangweilin.service.impl.ArticleServiceImpl">  
  98.         <property name="dao" ref="dao2" />  
  99.         <property name="loginLogService" ref="loginLogService2" />  
  100.     </bean>  
  101.       
  102.     <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean" />    
  103.     <!-- jtatransactionmanager容器 -->    
  104.     <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">    
  105.         <property name="userTransaction" ref="jotm" />    
  106.     </bean>    
  107.       
  108.      <tx:advice id="txAdvice2" transaction-manager="transactionManager">    
  109.         <tx:attributes>    
  110.             <tx:method name="add*" propagation="REQUIRED" />    
  111.             <tx:method name="upd*" propagation="REQUIRED" />    
  112.             <tx:method name="del*" propagation="REQUIRED" />    
  113.             <tx:method name="*" read-only="true" />  
  114.         </tx:attributes>    
  115.     </tx:advice>    
  116.       
  117.     <aop:config>    
  118.         <aop:pointcut id="interceptorPointCuts" expression="execution(* com.zhangweilin.service.*Service.*(..))" />    
  119.         <aop:advisor id="jotmAdvisor" advice-ref="txAdvice2" pointcut-ref="interceptorPointCuts" />    
  120.     </aop:config>   
  121. </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: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.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

<!-- jotm配置 -->
	<bean id="mysqldatasource" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource">  
        <property name="dataSource">
        <!--内部XA数据源  -->
            <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">  
                <property name="transactionManager" ref="jotm" />  
                <property name="driverName" value="com.mysql.jdbc.Driver" />  
                <property name="url" value="jdbc:mysql://172.16.18.75:3306/?useUnicode=true&amp;characterEncoding=UTF-8" />  
            </bean>  
        </property>  
        <property name="user" value="root" />  
        <property name="password" value="123456" />  
    </bean>  
  
  
    <bean id="h2datasource" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource">  
        <property name="dataSource">
       	 <!--内部XA数据源    -->
            <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">  
                <property name="transactionManager" ref="jotm" />  
                <property name="driverName" value="com.mysql.jdbc.Driver" />  
                <property name="url" value="jdbc:mysql://localhost:3306/pay?useUnicode=true&amp;characterEncoding=UTF-8" />  
            </bean>  
        </property>  
        <property name="user" value="zwllxs" />  
        <property name="password" value="123456" />  
    </bean>  
    
    <bean id="sessionFactory1" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
        <property name="dataSource" ref="mysqldatasource"/>  
        <property name="mappingDirectoryLocations">
			<list>
				<value>classpath*:/com/zhangweilin/po/</value>
			</list>
		</property>
        <property name="hibernateProperties">  
            <props>  
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>  
                <prop key="hibernate.show_sql">true</prop>  
                <prop key="hibernate.jdbc.batch_size">50</prop>  
                <prop key="hibernate.cache.use_query_cache">true</prop>  
                <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>  
            </props>  
        </property>  
        <!-- 
	        <property name="jtaTransactionManager">  
	            <ref bean="jotm" />  
	        </property>
         -->  
    </bean>  
    
     <bean id="sessionFactory2" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
            <property name="dataSource" ref="h2datasource"/>  
            <property name="mappingDirectoryLocations">
				<list>
					<value>classpath*:/com/zhangweilin/po/</value>
				</list>
			</property>
            <property name="hibernateProperties">  
                <props>  
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>  
                    <prop key="hibernate.show_sql">true</prop>  
                    <prop key="hibernate.jdbc.batch_size">50</prop>  
                    <prop key="hibernate.cache.use_query_cache">true</prop>  
                    <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>  
                </props>  
            </property>  
             <!-- 
		        <property name="jtaTransactionManager">  
		            <ref bean="jotm" />  
		        </property>
	         -->  
    </bean>  
    
    	
	<bean id="dao1" class="com.zhangweilin.core.DaoImpl">
		<property name="sessionFactory" ref="sessionFactory1" />
	</bean> 
    	
	<bean id="dao2" class="com.zhangweilin.core.DaoImpl">
		<property name="sessionFactory" ref="sessionFactory2" />
	</bean> 
	
	<bean id="loginLogService2" class="com.zhangweilin.service.impl.LoginLogServiceImpl">
		<property name="dao" ref="dao1" />
	</bean>
		
	<bean id="articleService2" class="com.zhangweilin.service.impl.ArticleServiceImpl">
		<property name="dao" ref="dao2" />
		<property name="loginLogService" ref="loginLogService2" />
	</bean>
	
	<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean" />  
    <!-- jtatransactionmanager容器 -->  
    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">  
        <property name="userTransaction" ref="jotm" />  
    </bean>  
    
     <tx:advice id="txAdvice2" transaction-manager="transactionManager">  
        <tx:attributes>  
            <tx:method name="add*" propagation="REQUIRED" />  
            <tx:method name="upd*" propagation="REQUIRED" />  
            <tx:method name="del*" propagation="REQUIRED" />  
			<tx:method name="*" read-only="true" />
        </tx:attributes>  
    </tx:advice>  
    
    <aop:config>  
        <aop:pointcut id="interceptorPointCuts" expression="execution(* com.zhangweilin.service.*Service.*(..))" />  
        <aop:advisor id="jotmAdvisor" advice-ref="txAdvice2" pointcut-ref="interceptorPointCuts" />  
    </aop:config> 
</beans>




再附上关键的service:
ArticleService.java:

Java代码 复制代码  收藏代码
  1. /** 
  2.  * 文章 
  3.  * @author zhangweilin 
  4.  * 
  5.  */  
  6. public interface ArticleService extends Service<Article>  
  7. {  
  8.     /** 
  9.      * 测试同时添加分布在不同库上的Article和LoginLog; 
  10.      * @param article 
  11.      * @throws Exception  
  12.      */  
  13.     public void addArticle(Article article,String name) throws Exception;  
  14.       
  15.       
  16.     public void setName(String name);  
  17.       
  18.     public String getName();  
  19. }  
/**
 * 文章
 * @author zhangweilin
 *
 */
public interface ArticleService extends Service<Article>
{
    /**
     * 测试同时添加分布在不同库上的Article和LoginLog;
     * @param article
     * @throws Exception 
     */
    public void addArticle(Article article,String name) throws Exception;
    
    
    public void setName(String name);
    
    public String getName();
}



ArticleServiceImpl.java:


Java代码 复制代码  收藏代码
  1. /** 
  2.  * 文章 
  3.  * @author zhangweilin 
  4.  * 
  5.  */  
  6. public class ArticleServiceImpl extends ServiceImpl<Article> implements ArticleService  
  7. {  
  8.     private LoginLogService loginLogService;  
  9.     private String name="张伟林";  
  10.     /** 
  11.      * @param loginLogService the loginLogService to set 
  12.      */  
  13.     public void setLoginLogService(LoginLogService loginLogService)  
  14.     {  
  15.         System.out.println("setLoginLogService: "+loginLogService);  
  16.         this.loginLogService = loginLogService;  
  17.     }  
  18.     @Override  
  19.     public void addArticle(Article article,String name) throws Exception  
  20.     {  
  21.          save(article);  
  22.          LoginLog loginLog=new LoginLog();  
  23.          loginLog.setAddress(name);  
  24.          loginLog.setAdmin(null);  
  25.          loginLog.setIp("11.11.11.11");  
  26. //         loginLog.setLoginTime(new Date());  
  27.            
  28.          System.out.println(" 添加");  
  29.          loginLogService.save(loginLog);  
  30.          System.out.println("操作结束");  
  31.     }  
  32.     @Override  
  33.     public String getName()  
  34.     {  
  35.         System.out.println("getName: "+name);  
  36.         return this.name;  
  37.     }  
  38.     @Override  
  39.     public void setName(String name)  
  40.     {  
  41.         System.out.println("setName: "+name);  
  42.         this.name=name;  
  43.           
  44.     }  
/**
 * 文章
 * @author zhangweilin
 *
 */
public class ArticleServiceImpl extends ServiceImpl<Article> implements ArticleService
{
    private LoginLogService loginLogService;
    private String name="张伟林";
    /**
     * @param loginLogService the loginLogService to set
     */
    public void setLoginLogService(LoginLogService loginLogService)
    {
        System.out.println("setLoginLogService: "+loginLogService);
        this.loginLogService = loginLogService;
    }
    @Override
    public void addArticle(Article article,String name) throws Exception
    {
         save(article);
         LoginLog loginLog=new LoginLog();
         loginLog.setAddress(name);
         loginLog.setAdmin(null);
         loginLog.setIp("11.11.11.11");
//         loginLog.setLoginTime(new Date());
         
         System.out.println(" 添加");
         loginLogService.save(loginLog);
         System.out.println("操作结束");
    }
    @Override
    public String getName()
    {
        System.out.println("getName: "+name);
        return this.name;
    }
    @Override
    public void setName(String name)
    {
        System.out.println("setName: "+name);
        this.name=name;
        
    }



再附上测试代码:


Java代码 复制代码  收藏代码
  1. package com.zhangweilin.test;  
  2.   
  3. import java.util.Date;  
  4.   
  5. import org.aopalliance.aop.Advice;  
  6. import org.junit.BeforeClass;  
  7. import org.junit.Test;  
  8. import org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor;  
  9. import org.springframework.beans.factory.BeanFactory;  
  10. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  11. import org.springframework.orm.hibernate3.HibernateTransactionManager;  
  12. import org.springframework.transaction.PlatformTransactionManager;  
  13. import org.springframework.transaction.jta.JtaTransactionManager;  
  14. import org.springframework.transaction.support.AbstractPlatformTransactionManager;  
  15.   
  16. import com.zhangweilin.po.Article;  
  17. import com.zhangweilin.service.ArticleService;  
  18. import com.zhangweilin.service.LoginLogService;  
  19.   
  20. /** 
  21.  * 测试在代码中动态切换spring的事务策略 
  22.  * @author wlzhang 
  23.  * 
  24.  */  
  25. public class TestServiceJotm  
  26. {  
  27.     private static BeanFactory fac;  
  28.     private static LoginLogService loginLogService2;  
  29.     private static ArticleService articleService;  
  30.     private static HibernateTransactionManager hibernateTransactionManager;  
  31.     private static PlatformTransactionManager platformTransactionManager;  
  32.     private static AbstractPlatformTransactionManager abstractPlatformTransactionManager;  
  33.       
  34.     /** 
  35.      * 初始化环境 
  36.      */  
  37.     @BeforeClass  
  38.     public static void init()  
  39.     {  
  40.         try  
  41.         {  
  42.   
  43.             fac = new ClassPathXmlApplicationContext("conf\\spring\\applicationContext*.xml");  
  44.             loginLogService2 = (LoginLogService) fac.getBean("loginLogService2");  
  45.             articleService = (ArticleService) fac.getBean("articleService2");  
  46.              
  47.         }  
  48.         catch (Throwable t)  
  49.         {  
  50.             t.printStackTrace();  
  51.         }  
  52.     }  
  53.       
  54.     /** 
  55.      * 尝试切换事务管理器 
  56.      */  
  57.     @Test  
  58.     public void testChangeTransactionManager()  
  59.     {  
  60.         //先测试单例效应  
  61.         System.out.println("articleService.name: "+articleService.getName());//第一次获取name值  
  62.         articleService.setName("伟林张");  
  63.         articleService = (ArticleService) fac.getBean("articleService2");  
  64.         System.out.println("articleService.name2: "+articleService.getName());//第二次获取name值,如果spring配置采用的单例,那么此获取的就是修改后的name值  
  65.           
  66.         //尝试着切换事务管理器  
  67.         Object jotm=fac.getBean("jotm");  
  68.         System.out.println("jotm: "+jotm+" , "+jotm.getClass());  
  69.   
  70.         Object interceptorPointCuts=fac.getBean("interceptorPointCuts");  
  71.         System.out.println("interceptorPointCuts: "+interceptorPointCuts+" , "+interceptorPointCuts.getClass());  
  72.           
  73.         DefaultBeanFactoryPointcutAdvisor jotmAdvisor=(DefaultBeanFactoryPointcutAdvisor) fac.getBean("jotmAdvisor");  
  74.         System.out.println("jotmAdvisor: "+jotmAdvisor+" , "+jotmAdvisor.getClass());  
  75.           
  76.         hibernateTransactionManager = (HibernateTransactionManager) fac.getBean("txManager");  
  77.         System.out.println("hibernateTransactionManager: "+hibernateTransactionManager);  
  78.           
  79.         platformTransactionManager = (PlatformTransactionManager) fac.getBean("transactionManager");  
  80.         System.out.println("platformTransactionManager: "+platformTransactionManager);  
  81.         System.out.println("切换前");  
  82.         if (platformTransactionManager instanceof JtaTransactionManager)  
  83.         {  
  84.             System.out.println("当前事务: JtaTransactionManager");  
  85.             JtaTransactionManager jtaTransactionManager=(JtaTransactionManager) platformTransactionManager;  
  86.             System.out.println("转成jtaTransactionManager: "+jtaTransactionManager);  
  87.             System.out.println("准备切换");  
  88.             platformTransactionManager=hibernateTransactionManager;  //尝试将hibernate事务管理器赋给jta事务管理器  
  89.             System.out.println("尝试切换成功:platformTransactionManager: "+platformTransactionManager);  
  90.               
  91.         }  
  92.         else if (platformTransactionManager instanceof HibernateTransactionManager)  
  93.         {  
  94.             System.out.println("当前事务: HibernateTransactionManager");  
  95.             HibernateTransactionManager jtaTransactionManager=(HibernateTransactionManager) platformTransactionManager;  
  96.             System.out.println("转成jtaTransactionManager: "+jtaTransactionManager);  
  97.         }  
  98.          
  99.         System.out.println("切换后");  
  100.         platformTransactionManager = (PlatformTransactionManager) fac.getBean("transactionManager");  
  101.         System.out.println("platformTransactionManager: "+platformTransactionManager);  
  102.         if (platformTransactionManager instanceof JtaTransactionManager)  
  103.         {  
  104.             //在“切换”后,还是调用的这里。说明切换不成功  
  105.             System.out.println("当前事务: JtaTransactionManager");  
  106.             JtaTransactionManager jtaTransactionManager=(JtaTransactionManager) platformTransactionManager;  
  107.             System.out.println("转成jtaTransactionManager: "+jtaTransactionManager);  
  108.             System.out.println("准备切换");  
  109.             platformTransactionManager=hibernateTransactionManager;  
  110.             System.out.println("尝试切换成功");  
  111.               
  112.         }  
  113.         else if (platformTransactionManager instanceof HibernateTransactionManager)  
  114.         {  
  115.             System.out.println("当前事务: HibernateTransactionManager");  
  116.             HibernateTransactionManager hibernateTransactionManager=(HibernateTransactionManager) platformTransactionManager;  
  117.             System.out.println("转成HibernateTransactionManager: "+hibernateTransactionManager);  
  118.         }  
  119.           
  120.         //结果,切换引用是行不通的,而更改现有的单例对象的值是可以的  
  121.     }  
  122.       
  123.     /** 
  124.      * 切换事务管理器失败,尝试切换 Advisor 
  125.      */  
  126.     @Test  
  127.     public void testChangeAdvisor()  
  128.     {  
  129.         DefaultBeanFactoryPointcutAdvisor jotmAdvisor=(DefaultBeanFactoryPointcutAdvisor) fac.getBean("jotmAdvisor");  
  130.         System.out.println("jotmAdvisor: "+jotmAdvisor+" , "+jotmAdvisor.getClass());  
  131.         System.out.println("jotmAdvisor: "+jotmAdvisor.getAdviceBeanName());  
  132.           
  133.         jotmAdvisor.setAdviceBeanName("txAdvice");  
  134.         jotmAdvisor=(DefaultBeanFactoryPointcutAdvisor) fac.getBean("jotmAdvisor");  
  135.         System.out.println("jotmAdvisor: "+jotmAdvisor.getAdviceBeanName());//adviceBeanName名被更改了,。幻想着切换事务的可行性增大了  
  136. //        Advice advice=jotmAdvisor.getAdvice();  
  137.     }  
  138.       
  139.     /** 
  140.      * 先不做切换的数据操作,完全符合自己预期 
  141.      * @throws Exception 
  142.      */  
  143.     @Test  
  144.     public void testArticleService() throws Exception  
  145.     {  
  146.         System.out.println("articleService: "+articleService);  
  147.           
  148.         Article article=new Article();  
  149.         article.setAddTime(new Date());  
  150.         article.setContent("太好了");  
  151.         article.setTitle("jotm测试下");  
  152.         article.setType(20);  
  153.           
  154.         articleService.addArticle(article,"上海");  
  155.     }  
  156.       
  157.       
  158.     /** 
  159.      * Advisor看起来貌似切换成功了,所以正式尝试切换事务来增加数据,测试中保证让数据库端一个表不能正常插入数据,以测试事务的一致性 
  160.      */  
  161.     @Test  
  162.     public void testChangeTrancation()  
  163.     {  
  164.         DefaultBeanFactoryPointcutAdvisor jotmAdvisor=(DefaultBeanFactoryPointcutAdvisor) fac.getBean("jotmAdvisor");  
  165.           
  166.         System.out.println("使用默认事务:jta事务");  
  167.           
  168.         Article article=new Article();  
  169.         article.setAddTime(new Date());  
  170.         article.setContent("使用默认事务:jta事务太好了");  
  171.         article.setTitle("使用默认事务:jta事务_jotm测试下");  
  172.         article.setType(20);  
  173.           
  174.         try  
  175.         {  
  176.             articleService.addArticle(article,"使用默认事务:jta事务_上海");  
  177.         }  
  178.         catch (Exception e)  
  179.         {  
  180.             // TODO Auto-generated catch block  
  181.             e.printStackTrace();  
  182.         }  
  183.           
  184.         jotmAdvisor.setAdviceBeanName("txAdvice2");  //尝试以更改adviceBeanName的方式修改指定的事务  
  185.         jotmAdvisor=(DefaultBeanFactoryPointcutAdvisor) fac.getBean("jotmAdvisor");  
  186.         System.out.println("事务已切换,使用本地事务");  
  187.           
  188.           
  189.         article=new Article();  
  190.         article.setAddTime(new Date());  
  191.         article.setContent("事务已切换,使用本地事务_事务太好了");  
  192.         article.setTitle("事务已切换,使用本地事务_jotm测试下");  
  193.         article.setType(20);  
  194.           
  195.         try  
  196.         {  
  197.             articleService.addArticle(article,"事务已切换,使用本地事务_上海");  
  198.         }  
  199.         catch (Exception e)  
  200.         {  
  201.             // TODO Auto-generated catch block  
  202.             e.printStackTrace();  
  203.         }  
  204.           
  205.         /** 
  206.          *  切换事务失败,事务的一致性并没有符合自己的预期。经过查询文档,关于setAdviceBeanName方法的描述如下, 
  207.          *  Specify the name of the advice bean that this advisor should refer to.  
  208.             An instance of the specified bean will be obtained on first access of this advisor&apos;s advice. This advisor will only ever obtain at most one single instance of  
  209.  
  210. the advice bean, caching the instance for the lifetime of the advisor.  
  211.          *  只在第一次访问时才创建,之后不能更改,哎,杯具 
  212.          */   
  213.            
  214.           
  215.     }  
  216.       
package com.zhangweilin.test;

import java.util.Date;

import org.aopalliance.aop.Advice;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.jta.JtaTransactionManager;
import org.springframework.transaction.support.AbstractPlatformTransactionManager;

import com.zhangweilin.po.Article;
import com.zhangweilin.service.ArticleService;
import com.zhangweilin.service.LoginLogService;

/**
 * 测试在代码中动态切换spring的事务策略
 * @author wlzhang
 *
 */
public class TestServiceJotm
{
    private static BeanFactory fac;
    private static LoginLogService loginLogService2;
    private static ArticleService articleService;
    private static HibernateTransactionManager hibernateTransactionManager;
    private static PlatformTransactionManager platformTransactionManager;
    private static AbstractPlatformTransactionManager abstractPlatformTransactionManager;
    
    /**
     * 初始化环境
     */
    @BeforeClass
    public static void init()
    {
        try
        {

            fac = new ClassPathXmlApplicationContext("conf\\spring\\applicationContext*.xml");
            loginLogService2 = (LoginLogService) fac.getBean("loginLogService2");
            articleService = (ArticleService) fac.getBean("articleService2");
           
        }
        catch (Throwable t)
        {
            t.printStackTrace();
        }
    }
    
    /**
     * 尝试切换事务管理器
     */
    @Test
    public void testChangeTransactionManager()
    {
        //先测试单例效应
        System.out.println("articleService.name: "+articleService.getName());//第一次获取name值
        articleService.setName("伟林张");
        articleService = (ArticleService) fac.getBean("articleService2");
        System.out.println("articleService.name2: "+articleService.getName());//第二次获取name值,如果spring配置采用的单例,那么此获取的就是修改后的name值
        
        //尝试着切换事务管理器
        Object jotm=fac.getBean("jotm");
        System.out.println("jotm: "+jotm+" , "+jotm.getClass());

        Object interceptorPointCuts=fac.getBean("interceptorPointCuts");
        System.out.println("interceptorPointCuts: "+interceptorPointCuts+" , "+interceptorPointCuts.getClass());
        
        DefaultBeanFactoryPointcutAdvisor jotmAdvisor=(DefaultBeanFactoryPointcutAdvisor) fac.getBean("jotmAdvisor");
        System.out.println("jotmAdvisor: "+jotmAdvisor+" , "+jotmAdvisor.getClass());
        
        hibernateTransactionManager = (HibernateTransactionManager) fac.getBean("txManager");
        System.out.println("hibernateTransactionManager: "+hibernateTransactionManager);
        
        platformTransactionManager = (PlatformTransactionManager) fac.getBean("transactionManager");
        System.out.println("platformTransactionManager: "+platformTransactionManager);
        System.out.println("切换前");
        if (platformTransactionManager instanceof JtaTransactionManager)
        {
            System.out.println("当前事务: JtaTransactionManager");
            JtaTransactionManager jtaTransactionManager=(JtaTransactionManager) platformTransactionManager;
            System.out.println("转成jtaTransactionManager: "+jtaTransactionManager);
            System.out.println("准备切换");
            platformTransactionManager=hibernateTransactionManager;  //尝试将hibernate事务管理器赋给jta事务管理器
            System.out.println("尝试切换成功:platformTransactionManager: "+platformTransactionManager);
            
        }
        else if (platformTransactionManager instanceof HibernateTransactionManager)
        {
            System.out.println("当前事务: HibernateTransactionManager");
            HibernateTransactionManager jtaTransactionManager=(HibernateTransactionManager) platformTransactionManager;
            System.out.println("转成jtaTransactionManager: "+jtaTransactionManager);
        }
       
        System.out.println("切换后");
        platformTransactionManager = (PlatformTransactionManager) fac.getBean("transactionManager");
        System.out.println("platformTransactionManager: "+platformTransactionManager);
        if (platformTransactionManager instanceof JtaTransactionManager)
        {
            //在“切换”后,还是调用的这里。说明切换不成功
            System.out.println("当前事务: JtaTransactionManager");
            JtaTransactionManager jtaTransactionManager=(JtaTransactionManager) platformTransactionManager;
            System.out.println("转成jtaTransactionManager: "+jtaTransactionManager);
            System.out.println("准备切换");
            platformTransactionManager=hibernateTransactionManager;
            System.out.println("尝试切换成功");
            
        }
        else if (platformTransactionManager instanceof HibernateTransactionManager)
        {
            System.out.println("当前事务: HibernateTransactionManager");
            HibernateTransactionManager hibernateTransactionManager=(HibernateTransactionManager) platformTransactionManager;
            System.out.println("转成HibernateTransactionManager: "+hibernateTransactionManager);
        }
        
        //结果,切换引用是行不通的,而更改现有的单例对象的值是可以的
    }
    
    /**
     * 切换事务管理器失败,尝试切换 Advisor
     */
    @Test
    public void testChangeAdvisor()
    {
        DefaultBeanFactoryPointcutAdvisor jotmAdvisor=(DefaultBeanFactoryPointcutAdvisor) fac.getBean("jotmAdvisor");
        System.out.println("jotmAdvisor: "+jotmAdvisor+" , "+jotmAdvisor.getClass());
        System.out.println("jotmAdvisor: "+jotmAdvisor.getAdviceBeanName());
        
        jotmAdvisor.setAdviceBeanName("txAdvice");
        jotmAdvisor=(DefaultBeanFactoryPointcutAdvisor) fac.getBean("jotmAdvisor");
        System.out.println("jotmAdvisor: "+jotmAdvisor.getAdviceBeanName());//adviceBeanName名被更改了,。幻想着切换事务的可行性增大了
//        Advice advice=jotmAdvisor.getAdvice();
    }
    
    /**
     * 先不做切换的数据操作,完全符合自己预期
     * @throws Exception
     */
    @Test
    public void testArticleService() throws Exception
    {
        System.out.println("articleService: "+articleService);
        
        Article article=new Article();
        article.setAddTime(new Date());
        article.setContent("太好了");
        article.setTitle("jotm测试下");
        article.setType(20);
        
        articleService.addArticle(article,"上海");
    }
    
    
    /**
     * Advisor看起来貌似切换成功了,所以正式尝试切换事务来增加数据,测试中保证让数据库端一个表不能正常插入数据,以测试事务的一致性
     */
    @Test
    public void testChangeTrancation()
    {
        DefaultBeanFactoryPointcutAdvisor jotmAdvisor=(DefaultBeanFactoryPointcutAdvisor) fac.getBean("jotmAdvisor");
        
        System.out.println("使用默认事务:jta事务");
        
        Article article=new Article();
        article.setAddTime(new Date());
        article.setContent("使用默认事务:jta事务太好了");
        article.setTitle("使用默认事务:jta事务_jotm测试下");
        article.setType(20);
        
        try
        {
            articleService.addArticle(article,"使用默认事务:jta事务_上海");
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        jotmAdvisor.setAdviceBeanName("txAdvice2");  //尝试以更改adviceBeanName的方式修改指定的事务
        jotmAdvisor=(DefaultBeanFactoryPointcutAdvisor) fac.getBean("jotmAdvisor");
        System.out.println("事务已切换,使用本地事务");
        
        
        article=new Article();
        article.setAddTime(new Date());
        article.setContent("事务已切换,使用本地事务_事务太好了");
        article.setTitle("事务已切换,使用本地事务_jotm测试下");
        article.setType(20);
        
        try
        {
            articleService.addArticle(article,"事务已切换,使用本地事务_上海");
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        /**
         *  切换事务失败,事务的一致性并没有符合自己的预期。经过查询文档,关于setAdviceBeanName方法的描述如下,
         *  Specify the name of the advice bean that this advisor should refer to. 
            An instance of the specified bean will be obtained on first access of this advisor&apos;s advice. This advisor will only ever obtain at most one single instance of 

the advice bean, caching the instance for the lifetime of the advisor. 
         *  只在第一次访问时才创建,之后不能更改,哎,杯具
         */ 
         
        
    }
    

   


  不知道有谁能提供更好的测试方案,如果有在代码中切换spring里的事务的方案更好
http://zwllxs.iteye.com/blog/1004081

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值