zoukankan      html  css  js  c++  java
  • SSM项目实现连接两个mysql数据库

    最近做项目需要用到另一个数据库的内容,多方查找终于实现了功能。

    我们都知道,在SSM框架中,我们在applicationContext.xml配置文件中添加数据源就可以实现数据库增删改查,但是只能连接一个数据库,这个时候我们就要从spring提供的源码下手看看有没有有关数据源切换的方法,找到关键源码(AbstractRoutingDataSource类,该类就相当于一个dataSource的调度者,用于根据key值来进行切换对应的dataSource。

    AbstractRoutingDataSource类:

    @Override
        public Connection getConnection() throws SQLException {
            return determineTargetDataSource().getConnection();
        }
     
        @Override
        public Connection getConnection(String username, String password) throws SQLException {
            return determineTargetDataSource().getConnection(username, password);
        }
     
        /**
         * Retrieve the current target DataSource. Determines the
         * {@link #determineCurrentLookupKey() current lookup key}, performs
         * a lookup in the {@link #setTargetDataSources targetDataSources} map,
         * falls back to the specified
         * {@link #setDefaultTargetDataSource default target DataSource} if necessary.
         * @see #determineCurrentLookupKey()
         */
        protected DataSource determineTargetDataSource() {
            Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
            Object lookupKey = determineCurrentLookupKey();
            DataSource dataSource = this.resolvedDataSources.get(lookupKey);
            if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
                dataSource = this.resolvedDefaultDataSource;
            }
            if (dataSource == null) {
                throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
            }
            return dataSource;
        }
     
        /**
         * Determine the current lookup key. This will typically be
         * implemented to check a thread-bound transaction context.
         * <p>Allows for arbitrary keys. The returned key needs
         * to match the stored lookup key type, as resolved by the
         * {@link #resolveSpecifiedLookupKey} method.
         */
        protected abstract Object determineCurrentLookupKey();

    可以看出方法getConnection()调用的determineTargetDataSource则是关键方法,这个方法返回了具体使用的是哪个数据库;而

    determineCurrentLookupKey()方法来返回当前数据源的key值。

    将返回的key值在resolvedDataSources这个map中找到对应的value(当前使用的数据源)。

    源码:

    @Override
        public void afterPropertiesSet() {
            if (this.targetDataSources == null) {
                throw new IllegalArgumentException("Property 'targetDataSources' is required");
            }
            this.resolvedDataSources = new HashMap<Object, DataSource>(this.targetDataSources.size());
            for (Map.Entry<Object, Object> entry : this.targetDataSources.entrySet()) {
                Object lookupKey = resolveSpecifiedLookupKey(entry.getKey());
                DataSource dataSource = resolveSpecifiedDataSource(entry.getValue());
                this.resolvedDataSources.put(lookupKey, dataSource);
            }
            if (this.defaultTargetDataSource != null) {
                this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource);
            }
        }

    这个方法是通过targetDataSources对resolvedDataSources进行赋值的。targetDataSources我们可以用过配置文件进行配置,这样就可以设置当前使用哪个数据库了,但是需要先要准备一下前提条件。

    第一步:我们先要重写上面的determineCurrentLookupKey方法,我们新建一个创建一个DynamicDataSource的类,用来获取自定义获取数据源的标识(和当前线程中使用的数据源):

    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
     
    public class DynamicDataSource extends AbstractRoutingDataSource {
     
        @Override
        protected Object determineCurrentLookupKey() {
            // 从自定义的位置获取数据源标识
            return DynamicDataSourceHolder.getDataSource();
        }
     
    }

    第二步:创建DynamicDataSourceHolder类用于切换要操作的数据源,代码如下:

    package com.dingdao.apiserver.utils;
     
    public class DynamicDataSourceHolder
    {
      private static final ThreadLocal<String> THREAD_DATA_SOURCE = new ThreadLocal();
      
      public static String getDataSource()
      {
        return (String)THREAD_DATA_SOURCE.get();
      }
      
      public static void setDataSource(String dataSource)
      {
        THREAD_DATA_SOURCE.set(dataSource);
      }
      
      public static void clearDataSource()
      {
        THREAD_DATA_SOURCE.remove();
      }
    }

    到这里我们的前期的准备工作已经做完了,下面将我的配置文件粘贴出来:

    jdbc.properties:

    driverClasss =com.mysql.jdbc.Driver(笔者用的mysql,如果不是mysql请自行替换)
    jdbcUrl=jdbc:第一个数据库的链接
    username=第一个数据库的用户名
    password=第一个数据库的密码
    jrt_driverClasss=com.mysql.jdbc.Driver(笔可以直接调用第一个的driverClasss,笔者只是用于看着舒服,啊哈哈)
    jrt_jdbcUrl=jdbc:第二个数据库的链接
    jrt_username=第二个数据库的用户名
    jrt_password=第二个数据库的密码
    #定义初始连接数
    initialSize=0
    #定义最大连接数
    maxActive=20
    #定义最大空闲
    maxIdle=20
    #定义最小空闲
    minIdle=1
    #定义最长等待时间
    maxWait=60000

    spring-mybatis.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                            http://www.springframework.org/schema/context
                            http://www.springframework.org/schema/context/spring-context-3.1.xsd
                            http://www.springframework.org/schema/tx
                            http://www.springframework.org/schema/tx/spring-tx.xsd">
     
        <!-- 自动扫描 -->
        <context:component-scan base-package="com.dingdao.apiserver.*"/>
     
        <!-- 第一种方式:加载一个properties文件 -->
        <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="location" value="classpath:jdbc.properties"/>
        </bean>
     
     
        
     
        <!-- 配置第一个数据源 -->
        <bean id="defultdataSource" class="org.apache.commons.dbcp.BasicDataSource"
              destroy-method="close">
            <property name="driverClassName" value="${driverClasss}"/>
            <property name="url" value="${jdbcUrl}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
            <!-- 初始化连接大小 -->
            <property name="initialSize" value="${initialSize}"></property>
            <!-- 连接池最大数量 -->
            <property name="maxActive" value="${maxActive}"></property>
            <!-- 连接池最大空闲 -->
            <property name="maxIdle" value="${maxIdle}"></property>
            <!-- 连接池最小空闲 -->
            <property name="minIdle" value="${minIdle}"></property>
            <!-- 获取连接最大等待时间 -->
            <property name="maxWait" value="${maxWait}"></property>
        </bean>
     
        <!-- 配置第二个数据源 -->
        <bean id="jrt_dataSource" class="org.apache.commons.dbcp.BasicDataSource"
              destroy-method="close">
            <property name="driverClassName" value="${jrt_driverClasss}"/>
            <property name="url" value="${jrt_jdbcUrl}"/>
            <property name="username" value="${jrt_username}"/>
            <property name="password" value="${jrt_password}"/>
            <!-- 初始化连接大小 -->
            <property name="initialSize" value="${initialSize}"></property>
            <!-- 连接池最大数量 -->
            <property name="maxActive" value="${maxActive}"></property>
            <!-- 连接池最大空闲 -->
            <property name="maxIdle" value="${maxIdle}"></property>
            <!-- 连接池最小空闲 -->
            <property name="minIdle" value="${minIdle}"></property>
            <!-- 获取连接最大等待时间 -->
            <property name="maxWait" value="${maxWait}"></property>
        </bean>
     
     
        <bean id="dataSource" class="com.dingdao.apiserver.utils.DynamicDataSource">
            <property name="targetDataSources">
                <map key-type="java.lang.String">
                    <!-- 指定lookupKey和与之对应的数据源,这里的key可以自行定义,要切换数据库的时候以key为标识,不要写错 -->
                    <entry key="defultdataSource" value-ref="defultdataSource"></entry>
                    <entry key="jrt_dataSource" value-ref="jrt_dataSource"></entry>
                </map>
            </property>
            <!-- 这里可以指定默认的数据源 -->
            <property name="defaultTargetDataSource" ref="defultdataSource" />
        </bean>
     
     
     
        <!-- mybatis和spring完美整合,不需要mybatis的配置映射文件 -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <!-- 自动扫描mapping.xml文件 -->
            <property name="mapperLocations" value="classpath:mapper/*.xml"></property>
        </bean>
     
        <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.dingdao.apiserver.dao"/>
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
        </bean>
     
     
        <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
        </bean>
     
        <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
        <tx:annotation-driven transaction-manager="transactionManager"/>
     
     
    </beans>

    使用默认数据库的时候可以什么都不用写,但是切换为非默认数据库的时候就要进行设置了,下面把调用两种数据库的方法贴出来:

    使用默认数据库的service的实现类代码:

     @Autowired
        @Qualifier("nitceDao")
        NitceDao nitceDao;
     
        public Map<String, Object> getNotice(Map<String, Object> map) {
            List<Map<String, Object>> notice = nitceDao.getNotice(map);
            Map<String,Object> maps = new HashMap<String, Object>();
            maps.put("lists", notice);
            return maps;
        }

    不适用默认数据库service的实现类代码:

     @Autowired
        @Qualifier("testJRTDao")
        private TestJRTDao testJRTDao;
     
        public String AllColor() {
            DynamicDataSourceHolder.setDataSource("jrt_dataSource");
            JSONObject jsonObject = new JSONObject();
            List<Map<String ,Object>> list = testJRTDao.selectAllColor();
            jsonObject.put("AllColor",list);
            return jsonObject.toString();
        }

    到这里两个数据库的切换已经可以实现了。

  • 相关阅读:
    MySQL锁之一:锁详解
    eclipse maven plugin 插件 安装 和 配置
    火星坐标系统
    使用Spring MVC统一异常处理实战
    websocket之二:WebSocket编程入门
    spring mvc 异常统一处理方式
    Android面向HTTP协议发送post请求
    用JAX-WS在Tomcat中公布WebService
    css3 -&gt; 多栏布局
    NSLayoutConstraint-代码实现自己主动布局的函数使用方法说明
  • 原文地址:https://www.cnblogs.com/MagicAsa/p/11089329.html
Copyright © 2011-2022 走看看