博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MyBatis配置多数据源
阅读量:6113 次
发布时间:2019-06-21

本文共 9325 字,大约阅读时间需要 31 分钟。

分类

MyBatis的多数据源配置分2种,

  1. 多数据源配置:两个库业务互不相干,a方法使用a库的数据,b方法使用b库的数据;
  2. 动态数据源配置:两个库业务有关联,如读写分离库。

第一种直接配置2个单独的数据源,不同模块引入不同的sqlSessionFactory即可;第二种需要配置可动态切换的数据源。

准备工作

两种方式都需要在pom.xml文件引入不同数据库需要的jar包,此处以MySQL和Oracle为例:

mysql
mysql-connector-java
5.1.40
com.oracle
ojdbc
7
复制代码

此处Oracle的jar包因为版权问题,在maven中央仓库中没有,需要手动安装。

多数据源配置

在applicationContext.xml中配置两套数据源即可

复制代码

此处第一个数据源指定去解析com/rebecca/mybatismutildb/mysql/**/dao/mapper包下的*Mapper.xml文件,即指定这些dao的方法去连MySQL的数据源;第二个数据源指定去解析com/rebecca/mybatismutildb/oracle/**/dao/mapper包下的*Mapper.xml文件,即指定这些dao的方法去连Oracle的数据源。

applicationContext.xml配置好后,直接在指定的包内编码即可。

动态数据源配置

  1. 在applicationContext.xml中配置动态切换数据源
classpath*:com/rebecca/mybatismutildb/mysql/**/dao/mapper/*Mapper.xml
classpath*:com/rebecca/mybatismutildb/oracle/**/dao/mapper/*Mapper.xml
复制代码
  1. applicationContext.xml中用到的相关类
  • DataSource 注解
package com.rebecca.mybatismutildb.db;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * DataSource的注解 * @Author: rebecca * @Date: Created in 2019/4/25 17:27 */@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.TYPE, ElementType.METHOD})public @interface DataSource {    String value();}复制代码
  • DataSourceAspect 切面
package com.rebecca.mybatismutildb.db;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.reflect.MethodSignature;import org.slf4j.LoggerFactory;import java.lang.reflect.Method;/** * 拦截所有带有注解@DataSource的类和方法 * @Author: rebecca * @Date: Created in 2019/4/25 17:28 */public class DataSourceAspect {    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(DataSourceAspect.class);    /**     * @Title: changeDataSource     * @Description: 拦截目标方法,获取由@DataSource指定的数据源标识,设置到线程存储中以便切换数据源     * @param joinPoint     * @return: void     */    public void changeDataSource(JoinPoint joinPoint){        Class
target = joinPoint.getTarget().getClass(); MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature(); for(Class
clazz : target.getInterfaces()){ resolveDataSource(clazz,methodSignature.getMethod()); } resolveDataSource(target,methodSignature.getMethod()); logger.debug("数据源切换至--->", DataSourceContextHolder.getDbType()); } private void resolveDataSource(Class
clazz, Method method){ try { if(clazz.isAnnotationPresent(DataSource.class)){ DataSource source = clazz.getAnnotation(DataSource.class); DataSourceContextHolder.setDbType(source.value()); } Class
[] types = method.getParameterTypes(); Method m = clazz.getDeclaredMethod(method.getName(), types); if(null != m && m.isAnnotationPresent(DataSource.class)){ DataSource source = m.getAnnotation(DataSource.class); DataSourceContextHolder.setDbType(source.value()); } } catch (Exception e) { e.printStackTrace(); } } public void removeDataSource() { try { DataSourceContextHolder.clearDbType(); logger.debug("数据源已移除!"); } catch (Exception e) { e.printStackTrace(); logger.debug("数据源移除报错!", e); } }}复制代码
  • DataSourceContextHolder 类
package com.rebecca.mybatismutildb.db;/** * @Author: rebecca * @Description: * @Date: Created in 2019/3/28 11:43 * @Modified By: */public class DataSourceContextHolder {    // 注意此处的属性值要与applicationContext.xml中配置的一致    public static final String DATA_SOURCE_MYSQL = "mysqlDtaSource";    public static final String DATA_SOURCE_ORACLE = "oracleDataSource";    //用ThreadLocal来设置当前线程使用哪个dataSource    private static final ThreadLocal
contextHolder = new ThreadLocal
(); public static void setDbType(String customerType) { contextHolder.set(customerType); } public static String getDbType() { return contextHolder.get(); } public static void clearDbType() { contextHolder.remove(); }}复制代码
  • DynamicDataSource 类
package com.rebecca.mybatismutildb.db;import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;import java.util.logging.Logger;/** * 动态切换数据源 * @Author: rebecca * @Description: * @Date: Created in 2019/3/28 11:42 * @Modified By: */public class DynamicDataSource extends AbstractRoutingDataSource {    @Override    protected Object determineCurrentLookupKey() {        return DataSourceContextHolder.getDbType();    }    @Override    public Logger getParentLogger() {        return null;    }}复制代码
  • PackagesSqlSessionFactoryBean 类(自定义实现SqlSessionFactoryBean,以支持mapperLocations的通配符配置)
package com.rebecca.mybatismutildb.db;import org.apache.commons.lang.StringUtils;import org.mybatis.spring.SqlSessionFactoryBean;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.core.io.Resource;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import org.springframework.core.io.support.ResourcePatternResolver;import org.springframework.core.type.classreading.CachingMetadataReaderFactory;import org.springframework.core.type.classreading.MetadataReader;import org.springframework.core.type.classreading.MetadataReaderFactory;import org.springframework.util.ClassUtils;import java.io.IOException;import java.util.ArrayList;import java.util.List;/** * 支持包名的通配符解析 * @Author: rebecca * @Description: * @Date: Created in 2019/3/28 15:30 * @Modified By: */public class PackagesSqlSessionFactoryBean extends SqlSessionFactoryBean {    static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";    private Logger logger = LoggerFactory.getLogger(PackagesSqlSessionFactoryBean.class);    @Override    public void setTypeAliasesPackage(String typeAliasesPackage) {        ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();        MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);        typeAliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +                ClassUtils.convertClassNameToResourcePath(typeAliasesPackage) + "/" + DEFAULT_RESOURCE_PATTERN;        // 将加载多个绝对匹配的所有Resource        // 将首先通过ClassLoader.getResource("META-INF")加载非模式路径部分        // 然后进行遍历模式匹配        try {            List
result = new ArrayList
(); Resource[] resources = resolver.getResources(typeAliasesPackage); if(resources != null && resources.length > 0){ MetadataReader metadataReader = null; for(Resource resource : resources){ if(resource.isReadable()){ metadataReader = metadataReaderFactory.getMetadataReader(resource); try { result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName()); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } } if(result.size() > 0) { super.setTypeAliasesPackage(StringUtils.join(result.toArray(), ",")); }else{ logger.warn("参数typeAliasesPackage:"+typeAliasesPackage+",未找到任何包"); } } catch (IOException e) { e.printStackTrace(); } }}复制代码
  1. 在对应的dao的接口上,增加@DataSource(string value)注解,其中value的值是DataSourceContextHolder.DATA_SOURCE_MYSQLDataSourceContextHolder.DATA_SOURCE_ORACLE
    因为在applicationContext.xml中配置的默认数据库连接是MySQL,所以在连MySQL库的接口上可以不写@DataSource(string value)注解。同样,此注解也可以加在接口的方法上。

参考链接

转载于:https://juejin.im/post/5cc57880f265da03b858597b

你可能感兴趣的文章
cocos2d-x Schedule详解
查看>>
sdut 2163:Identifiers(第二届山东省省赛原题,水题)
查看>>
C++ 容器:顺序性容器、关联式容器和容器适配器
查看>>
mysql 常用语句集
查看>>
Atitit.软件开发提升稳定性总结
查看>>
lftp查看文件时间与登录服务查看文件时间相差8小时
查看>>
[leetcode]Next Permutation @ Python
查看>>
JAVA(2)——JDBC
查看>>
php heredoc 与 nowdoc
查看>>
DBA_Oracle DBA常用表汇总(概念)
查看>>
第30周二
查看>>
数学类杂志SCI2013-2014影响因子
查看>>
实用的树形菜单控件tree
查看>>
最近公共祖先(lca)
查看>>
【WP 8.1开发】文件选取器的使用方法
查看>>
Java实现BASE64编解码
查看>>
【Java】java基本知识
查看>>
之前学习wordpress的几张图片
查看>>
RT-Thread下的串口驱动程序分析【转载】
查看>>
UITableView的UITableViewStyleGrouped
查看>>