实习的时候,公司的项目要求使用公司组件来连接数据库,并且要同时使用两个数据库。查过很多资料,踩过很多坑,还是记录下来吧。

项目核心为写一个继承AbstractRoutingDataSource 的类,并用aop来实现动态切换数据源。此项目已经配置了两个datasource。

动态数据源配置


/**
* 动态数据源
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getDatabaseType();
}
}

写一个枚举类来定义key


public enum DatabaseType {
RESOURCE,
ORDER
}

保存一个线程安全的DatabaseType容器


public class DatabaseContextHolder {
private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<DatabaseType>();

public static DatabaseType getDatabaseType() {
return contextHolder.get() == null ? DatabaseType.ORDER : contextHolder.get();
}

public static void setDatabaseType(DatabaseType dbType) {
if (dbType == null) throw new NullPointerException("dbType must not be null");
contextHolder.set(dbType);
}

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

配置mybatis


@Bean
public AbstractRoutingDataSource routingDataSource(@Qualifier("resource")DataSource resourceDataSource,@Qualifier("order") DataSource orderDataSource){
Map<Object,Object> targetDataSource=new HashMap<Object, Object>();
targetDataSource.put(DatabaseType.RESOURCE,resourceDataSource);
targetDataSource.put(DatabaseType.ORDER,orderDataSource);
AbstractRoutingDataSource routingDataSource=new DynamicDataSource();
routingDataSource.setTargetDataSources(targetDataSource);
routingDataSource.setDefaultTargetDataSource(orderDataSource);//设置默认的datasource
return routingDataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory(AbstractRoutingDataSource routingDataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean=new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(routingDataSource);
SqlSessionFactory sqlSessionFactory=sqlSessionFactoryBean.getObject();
return sqlSessionFactory;
}

写一个aop,当不使用默认的datasource时切换数据源


@Aspect
@Component
public class DataSourceAspect {
@Pointcut("execution(* com.service.resource.impl.*.*(..))")
public void resource(){}
@Before(value ="resource()")
public void before(JoinPoint joinPoint){
DatabaseContextHolder.setDatabaseType(DatabaseType.RESOURCE);
}
@After(value = "resource()")
public void after(JoinPoint joinPoint){
DatabaseContextHolder.setDatabaseType(DatabaseType.ORDER);
}
}