zoukankan      html  css  js  c++  java
  • Spring MVC+Mybatis 多数据源配置及发现的几个问题

    1.CustomerContextHolder 数据源管理类,负责管理当前的多个数据源,基于ThreadLocal实现,对每个线程设置不同的目标数据源

    public class CustomerContextHolder {
        private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
    
        public static void setCustomerType(String customerType) {
            contextHolder.set(customerType);
        }
    
        public static void clearCustomerType() {
            contextHolder.remove();
        }
    
        public static String getCustomerType() {
            return contextHolder.get();
        }
    }

    2.DynamicDataSource 数据注入类

    public class DynamicDataSource extends AbstractRoutingDataSource {
        @Override
        protected Object determineCurrentLookupKey() {
            return CustomerContextHolder.getCustomerType();
        }
    }

    3.配置文件

      a)spring-context-data-source.xml

      

    <!--统一的dataSource -->
        <bean id="dataSource" class="com.thinkgem.jeesite.common.config.DynamicDataSource">
            <property name="targetDataSources">
                <map key-type="java.lang.String">
                    <entry value-ref="a" key="a"></entry>
                    <entry value-ref="b" key="b"></entry>
                </map>
            </property>
            <property name="defaultTargetDataSource" ref="a">
            </property>
        </bean>
    
    
        <!-- 数据源配置, 使用 BoneCP 数据库连接池 -->
        <bean id="a" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
            <!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
            <property name="driverClassName" value="${jdbc.driver}" />
            <!-- 基本属性 url、user、password -->
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
            <!-- 配置初始化大小、最小、最大 -->
            <property name="initialSize" value="${jdbc.pool.init}" />
            <property name="minIdle" value="${jdbc.pool.minIdle}" />
            <property name="maxActive" value="${jdbc.pool.maxActive}" />
            <!-- 配置获取连接等待超时的时间 -->
            <property name="maxWait" value="60000" />
            <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
            <property name="timeBetweenEvictionRunsMillis" value="60000" />
            <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
            <property name="minEvictableIdleTimeMillis" value="300000" />
            <property name="validationQuery" value="${jdbc.testSql}" />
            <property name="testWhileIdle" value="true" />
            <property name="testOnBorrow" value="false" />
            <property name="testOnReturn" value="false" />
            <!-- 打开PSCache,并且指定每个连接上PSCache的大小(Oracle使用) <property name="poolPreparedStatements" value="true" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="20" /> -->
            <!-- 配置监控统计拦截的filters -->
            <property name="filters" value="stat" />
        </bean>
    
        <!-- 数据源配置, 使用 BoneCP 数据库连接池 -->
        <bean id="b" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
            <!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
            <property name="driverClassName" value="${jdbc.driver}" />
            <!-- 基本属性 url、user、password -->
            <property name="url" value="${jdbc.url.kpidata}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
            <!-- 配置初始化大小、最小、最大 -->
            <property name="initialSize" value="${jdbc.pool.init}" />
            <property name="minIdle" value="${jdbc.pool.minIdle}" />
            <property name="maxActive" value="${jdbc.pool.maxActive}" />
            <!-- 配置获取连接等待超时的时间 -->
            <property name="maxWait" value="60000" />
            <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
            <property name="timeBetweenEvictionRunsMillis" value="60000" />
            <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
            <property name="minEvictableIdleTimeMillis" value="300000" />
            <property name="validationQuery" value="${jdbc.testSql}" />
            <property name="testWhileIdle" value="true" />
            <property name="testOnBorrow" value="false" />
            <property name="testOnReturn" value="false" />
            <!-- 打开PSCache,并且指定每个连接上PSCache的大小(Oracle使用) <property name="poolPreparedStatements" value="true" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="20" /> -->
            <!-- 配置监控统计拦截的filters -->
            <property name="filters" value="stat" />
        </bean>

      b)spring-context.xml mybatis的配置

    <!-- MyBatis begin -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="mapperLocations" value="classpath:/mappings/**/*.xml"/>
            <property name="configLocation" value="classpath:/mybatis-config.xml"></property>
        </bean>
        
        <!-- 扫描basePackage下所有以@MyBatisDao注解的接口 -->
        <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
            <property name="basePackage" value="com.thinkgem.jeesite"/>
            <property name="annotationClass" value="com.thinkgem.jeesite.common.persistence.annotation.MyBatisDao"/>
        </bean>

    4.使用 

      @ResponseBody
        @RequestMapping(value = "jeesiteDb")
        public Map<String, Object> jeesiteDb() {
            Map<String, Object> returnMap = new HashMap<String, Object>();
            CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_JEESITE);
            List<Map<String, String>> list = testService.queryJeesite();
            returnMap.put("data", list);
            return returnMap;
        }
    
        @ResponseBody
        @RequestMapping(value = "myTestDb")
        public Map<String, Object> myTestDb() {
            Map<String, Object> returnMap = new HashMap<String, Object>();
            CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_MT_TEST);
            List<Map<String, String>> list = testService.queryMyTest();
            returnMap.put("data", list);
            return returnMap;
        }

    5.问题

      a) 请求数据源的方法一定要写在controller中,不要写在dao中

    CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_MT_TEST);

      b) 如果是同一个controller中,不同方法请求不同的数据源,上面的写法足够了,但是如果要统一个方法动态指定数据源,那么需要在使用之后加上,清除当前线程的数据源,否则数据切换会失败

    CustomerContextHolder.clearCustomerType();
  • 相关阅读:
    Win10 UWP Tile Generator
    Win10 BackgroundTask
    UWP Tiles
    UWP Ad
    Win10 build package error collections
    Win10 八步打通 Nuget 发布打包
    Win10 UI入门 pivot multiable DataTemplate
    Win10 UI入门 导航滑动条 求UWP工作
    UWP Control Toolkit Collections 求UWP工作
    Win10 UI入门 SliderRectangle
  • 原文地址:https://www.cnblogs.com/Yiran583/p/6656306.html
Copyright © 2011-2022 走看看