Spring+iBatis+Atomikos实现JTA事务

实现分布式事务管理

  网上有很多都是配置2甚至多个一样的Dao去实现此操作,小弟修改了一下ibatis源代码使得dao层可以动态指定数据源。


Spring配置文件

<tx:advice id="txAdvice" transaction-manager="transactionManager">
	<tx:attributes>
		<tx:method name="insert*" propagation="REQUIRED" />
		<tx:method name="delete*" propagation="REQUIRED" />
		<tx:method name="update*" propagation="REQUIRED" />
		<tx:method name="*" read-only="true" />
	</tx:attributes>
</tx:advice>


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


<!--配置jta transactionManager-->
<bean id="transactionManager"
 class="org.springframework.transaction.jta.JtaTransactionManager">  
 <property name="transactionManager">  
            <ref bean="atomikosTransactionManager" />  
       </property>  
       <property name="userTransaction">  
            <ref bean="atomikosUserTransaction" />  
       </property>  
       <property name="allowCustomIsolationLevels" value="true"/>
</bean>
 <bean id="atomikosTransactionManager"  
        class="com.atomikos.icatch.jta.UserTransactionManager"   
        init-method="init" destroy-method="close">  
       <property name="forceShutdown">  
                <value>true</value>  
        </property>  
 </bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">   
        <property name="transactionTimeout">  
              <value>20000</value>  
        </property>  
 </bean> 
<!--配置数据源 -->
<bean id="datasource1" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">      
         <property name="uniqueResourceName">      
             <value>oracle/read</value>      
         </property>      
         <property name="xaDataSourceClassName">      
             <value>oracle.jdbc.xa.client.OracleXADataSource</value>      
         </property>      
         <property name="xaProperties">  
                <props>
                <prop key="user">customer</prop>
                <prop key="password">123456</prop>
                <prop key="URL">jdbc:oracle:thin:@localhost:1521:jddb</prop>
                </props>     
          </property> 
          <property name="maxPoolSize"><value>10</value></property>  
          <property name="minPoolSize"><value>2</value></property>  
          <property name="loginTimeout"><value>30</value></property>  
          <property name="reapTimeout"><value>20000</value></property>  
         <property name="testQuery">  <value>select 1 from dual</value>  </property> 
     </bean>

<bean id="datasource2" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">      
         <property name="uniqueResourceName">      
             <value>oracle/read</value>      
         </property>      
         <property name="xaDataSourceClassName">      
             <value>oracle.jdbc.xa.client.OracleXADataSource</value>      
         </property>      
         <property name="xaProperties">  
                <props>
                <prop key="user">customer</prop>
                <prop key="password">123456</prop>
                <prop key="URL">jdbc:oracle:thin:@192.168.0.2:1521:jddb</prop>
                </props>     
          </property> 
          <property name="maxPoolSize"><value>10</value></property>  
          <property name="minPoolSize"><value>2</value></property>  
          <property name="loginTimeout"><value>30</value></property>  
          <property name="reapTimeout"><value>20000</value></property>  
         <property name="testQuery">  <value>select 1 from dual</value>  </property> 
     </bean>

<!--配置 sqlMapClient -->
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
       <property name="configLocation" value="classpath:sqlMapConfig.xml"></property>
       <property name="dataSource" ref="datasource1" />
    </bean>
    <bean id="sqlMapClient2" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
       <property name="configLocation" value="classpath:sqlMapConfig2.xml"></property>
       <property name="dataSource" ref="datasource2" />
    </bean>

<!-- 增加此属性,为了在dao层和service动态分配sqlMapClient -->
<bean id="sqlMapClientMap" class="com.home.framework.dynamicds.SqlMapClientMap">
    <property name="map">
      <map key-type="java.lang.String">
         <entry key="READ1" value-ref="sqlMapClient" />
         <entry key="WRITE" value-ref="sqlMapClient2" />
      </map>
    </property>
</bean>


SqlMapClientMap.java源代码
public class SqlMapClientMap {

	private LinkedHashMap<String,SqlMapClient> map = new LinkedHashMap<String,SqlMapClient>();

	public LinkedHashMap<String,SqlMapClient> getMap() {
		return map;
	}

	public void setMap(LinkedHashMap<String,SqlMapClient> map) {
		this.map = map;
	}
	
	
}



jta.properties配置文件

com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory

com.atomikos.icatch.console_file_name = tm.out

com.atomikos.icatch.log_base_name = tmlog

com.atomikos.icatch.tm_unique_name = tm

com.atomikos.icatch.console_log_level=INFO



修改ibatis源文件SqlMapClientDaoSupport
1.增加属性(set get方法省略)

//当前调用sqlMap名称
protected String sqlMapClientName;
//配置文件注入sqlMap集合
private SqlMapClientMap sqlMapClientMap = new SqlMapClientMap();



2.修改方法
public final SqlMapClientTemplate getSqlMapClientTemplate() {
    if(sqlMapClientName == null) {
    
    } else {
         SqlMapClient sqlMapClient = sqlMapClientMap.getMap().get(sqlMapClientName);
         this.sqlMapClientTemplate.setSqlMapClient(sqlMapClient);
    }
    return this.sqlMapClientTemplate;
}




public class DataSourceContextHolder {
	private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();

	public static void setCustomerType(String customerType) {
		contextHolder.set(customerType);
	}

	public static String getCustomerType() {
		return (String) contextHolder.get();
	}

	public static void clearCustomerType() {
		contextHolder.remove();
	}

}

public class DataSourceMap {
	public static final String READ1 = "READ1";
	public static final String WRITE = "WRITE";
}

Dao层代码
@Component("iFunocxDao")
public class FunocxDao extends SqlMapClientDaoSupport implements IFunocxDao {

	public void insert(Object o) {
		// TODO Auto-generated method stub
                sqlMapClientName = DataSourceContextHolder.getCustomerType();
		getSqlMapClientTemplate().insert(o)
	}

}

Service层代码
@Service("iFunocxService")
public class FunocxService implements IFunocxService {
	
	@Autowired
	private IFunocxDao iFunocxDao;


	public void insert(Funocx ocx) {
		// TODO Auto-generated method stub
            DataSourceContextHolder.setCustomerType(DataSourceMap.WRITE);
	    iFunocxDao.insert(ocx);

            DataSourceContextHolder.setCustomerType(DataSourceMap.WRITE);
	    iFunocxDao.insert(ocx);
	}

}

你可能感兴趣的:(java,DAO,spring,oracle,ibatis)