1、pom.xml
<atomikos.version>4.0.2</atomikos.version>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>atomikos-util</artifactId>
<version>${atomikos.version}</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions</artifactId>
<version>${atomikos.version}</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jta</artifactId>
<version>${atomikos.version}</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jdbc</artifactId>
<version>${atomikos.version}</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-api</artifactId>
<version>${atomikos.version}</version>
</dependency>
2、多數據源:
public class DynamicDataSourceContextHolder
{
public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);
/**
* 使用ThreadLocal維護變量,ThreadLocal爲每個使用該變量的線程提供獨立的變量副本,
* 所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應的副本。
*/
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
/**
* 設置數據源的變量
*/
public static void setDateSoureType(String dsType)
{
log.info("切換到{}數據源", dsType);
CONTEXT_HOLDER.set(dsType);
}
/**
* 獲得數據源的變量
*/
public static String getDateSoureType()
{
return CONTEXT_HOLDER.get();
}
/**
* 清空數據源變量
*/
public static void clearDateSoureType()
{
CONTEXT_HOLDER.remove();
}
}
@Aspect
@Order(1)
@Component
public class DsAspect
{
@Pointcut("@annotation(com.test.datasource.Ds)")
public void dsPointCut()
{
}
@Around("dsPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable
{
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
Ds dataSource = method.getAnnotation(Ds.class);
if (dataSource != null)
{
DynamicDataSourceContextHolder.setDateSoureType(dataSource.value().name());
}
try
{
return point.proceed();
}
finally
{
// 銷燬數據源 在執行方法之後
DynamicDataSourceContextHolder.clearDateSoureType();
}
}
}
3、創建一個類CustomSqlSessionTemplate繼承org.mybatis.spring.SqlSessionTemplate
並重寫getSqlSessionFactory()方法
4、spring-mybatis.xml
<bean id="dataSourceA" class="com.atomikos.jdbc.AtomikosDataSourceBean" destroy-method="close">
<property name="uniqueResourceName" value="one" />
<property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
<property name="xaProperties">
<props>
<prop key="url">${jdbc.url}</prop>
<prop key="user">${jdbc.username}</prop>
<prop key="password">${jdbc.password}</prop>
</props>
</property>
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="20" />
<property name="maxIdleTime" value="60" />
<property name="reapTimeout" value="20000" />
</bean>
<!--數據源2-->
<bean id="dataSourceB" class="com.atomikos.jdbc.AtomikosDataSourceBean" destroy-method="close">
<property name="uniqueResourceName" value="two" />
<property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
<property name="xaProperties">
<props>
<prop key="url">${slave.url}</prop>
<prop key="user">${slave.username}</prop>
<prop key="password">${slave.password}</prop>
</props>
</property>
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="20" />
<property name="maxIdleTime" value="60" />
<property name="reapTimeout" value="20000" />
</bean>
<bean id="sqlSessionFactoryA" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSourceA" />
<property name="mapperLocations" value="classpath:com/test/**/*.xml"></property>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<value>
helperDialect=mysql
reasonable=true
supportMethodsArguments=true
params=count=countSql
autoRuntimeDialect=true
</value>
</property>
</bean>
</array>
</property>
</bean>
<bean id="sqlSessionFactoryB" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSourceB" />
<property name="mapperLocations" value="classpath:com/test/**/*.xml"></property>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<value>
helperDialect=mysql
reasonable=true
supportMethodsArguments=true
params=count=countSql
autoRuntimeDialect=true
</value>
</property>
</bean>
</array>
</property>
</bean>
<bean id="sqlSessionTemplate" class="com.test.datasource.CustomSqlSessionTemplate">
<constructor-arg ref="sqlSessionFactoryA" />
<property name="targetSqlSessionFactorys">
<map>
<entry key="MASTER" value-ref="sqlSessionFactoryA" />
<entry key="SLAVE" value-ref="sqlSessionFactoryB" />
</map>
</property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.test.**.mapper" />
<property name="sqlSessionTemplateBeanName" value="sqlSessionTemplate"></property>
</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="300" />
</bean>
<bean id="springTransactionManager"
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>
<tx:annotation-driven transaction-manager="springTransactionManager" proxy-target-class="true" order="2" />
5、service方面: