实习的时候,公司的项目要求使用公司组件来连接数据库,并且要同时使用两个数据库。查过很多资料,踩过很多坑,还是记录下来吧。
项目核心为写一个继承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); } }