db

spring动态创建数据源、动态切换数据源

2018-11-22  本文已影响0人  舒尔诚

1、创建动态数据源RoutingDataSource

package com.yhbc.datasourceT;

import java.util.HashMap;

import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;

import org.hibernate.SessionFactory;

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.context.ApplicationContext;

import org.springframework.context.ApplicationContextAware;

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import org.springframework.stereotype.Component;

import com.alibaba.druid.pool.DruidDataSource;

//@Component  不能有这个注解 ,xml的bean比他晚生成

public class RoutingDataSource extends AbstractRoutingDataSource  {

private  Map dataSources = new HashMap<>();

//@Autowired

//@Qualifier("dataSource")//根据xml的id写

private DruidDataSource defaultTargetDataSource ;//主数据源注入

JdbcTemplate jdbcTemplate;

protected SessionFactory sessionFactory;

@Override

protected DataSource determineTargetDataSource() {

// 根据数据库选择方案,拿到要访问的数据库

        String dataSourceName = (String) determineCurrentLookupKey();

        if(RoutingDataSourceContext.MASTER_DATASOURCE.equals(dataSourceName)) {

            // 访问默认主库

            return defaultTargetDataSource;

        }

        // 根据数据库名字,从已创建的数据库中获取要访问的数据库

        return (DataSource) this.dataSources.get(dataSourceName);

}

@Override

    protected Object determineCurrentLookupKey() {

    System.out.println("---determineCurrentLookupKey-----主数据源=="+defaultTargetDataSource);

        String dbName = RoutingDataSourceContext.getDataSourceRoutingKey();

        if (StringUtils.isEmpty(dbName)) {

        return RoutingDataSourceContext.getMainKey();

        }

        if (!dataSources.containsKey(dbName)){

            createAndSaveDataSource(dbName);

        }

        return dbName;

    }

    private synchronized void createAndSaveDataSource(String dbName) {

        DruidDataSource dataSource = createDruidDataSource(dbName);

        dataSources.put(dbName, dataSource);

        super.setTargetDataSources(dataSources);

        afterPropertiesSet();

    }

    /**

    * 根据配置创建DruidDataSource

    * @param fanDataSource

    * @return

    */

    public  DruidDataSource createDruidDataSource(String dbName ) {

    if(dataSources.containsKey(dbName)){

    return (DruidDataSource) dataSources.get(dbName);

    }

        DruidDataSource dataSource = new DruidDataSource();

        dataSource.setDriverClassName("com.mysql.jdbc.Driver");

        dataSource.setName(dbName);

        dataSource.setUrl("jdbc:mysql://192.168.1.13:3306/"+dbName+"?useUnicode=true&allowMultiQueries=true&useSSL=false");

        dataSource.setUsername("root");

        dataSource.setPassword("root");

        dataSource.setInitialSize(2);

        // 从池中取得链接时做健康检查,该做法十分保守

        dataSource.setTestOnBorrow(true);

        // 如果连接空闲超过1小时就断开

        dataSource.setMinEvictableIdleTimeMillis(1 * 60000 * 60);

        // 每十分钟验证一下连接

        dataSource.setTimeBetweenEvictionRunsMillis(600000);

        // 运行ilde链接测试线程,剔除不可用的链接

        dataSource.setTestWhileIdle(true);

        dataSource.setMaxWait(-1);

        return dataSource;

    }

    /*public RoutingDataSource() {

    //创建主库

      // createAndSaveDataSource(RoutingDataSourceContext.getMainKey());

        dataSources.put(RoutingDataSourceContext.MASTER_DATASOURCE,defaultTargetDataSource );

        System.out.println("构造动态数据源,加入主数据源=="+defaultTargetDataSource);

        DruidDataSource dataSource = createDruidDataSource();

        jdbcTemplate = new JdbcTemplate();

        jdbcTemplate.setDataSource(dataSource);

        System.out.println("===========testQy========="+testQy());

  }*/

    /**

    * 通过jdbc从数据库中查找数据源配置

    * @param name

    * @return

    */

    private int testQy() {

        String sql = "select id  from box_function  where url='1-supplyCodeList.htm' ";

      // RowMapper<FanDataSource> rowMapper = new BeanPropertyRowMapper<>(FanDataSource.class);

        int  id = jdbcTemplate.queryForInt(sql);

        return id;

    }

public void setDefaultTargetDataSource(DruidDataSource defaultTargetDataSource) {

System.out.println("---setDefaultTargetDataSource-----主数据源=="+defaultTargetDataSource);

this.defaultTargetDataSource = defaultTargetDataSource;

}

}

2、创建线程切换类RoutingDataSourceContext,用来切换数据库的名称

package com.yhbc.datasourceT;

public class RoutingDataSourceContext  {

    static final ThreadLocal<String> threadLocalDataSourceKey = new ThreadLocal<>();

    public static final String MASTER_DATASOURCE="defaultDataSource";

    /**

    * 获取主数据库的key

    * @return

    */

    public static String getMainKey() {

        return MASTER_DATASOURCE;

    }

    /**

    * 获取数据库key

    * @return

    */

    public static String getDataSourceRoutingKey() {

        String key = threadLocalDataSourceKey.get();

        return key == null ? getMainKey() : key;

    }

    /**

    * 设置数据库的key

    * @param key

    */

    public static void setThreadLocalDataSourceKey(String key) {

        threadLocalDataSourceKey.set(key);

    }

}

3、关键的一步,数据源关联session

仔细观察哦,routingDataSource在bean中,赋予sessionFactory

<beans:bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">

<beans:property name="driverClassName" value="${silverbox.driver}" />

<beans:property name="url" value="${silverbox.url}" />

<beans:property name="username" value="${silverbox.username}" />

<beans:property name="password" value="${silverbox.password}" />

<beans:property name="maxActive" value="${silverbox.maxActive}" />

<beans:property name="validationQuery" value="${silverbox.testSql}"/>

<beans:property name="testWhileIdle" value="true"/>

<beans:property name="initialSize" value="${silverbox.initialSize}"/>

<beans:property name="maxWait" value="${silverbox.maxWait}"/>

</beans:bean>

<beans:bean id="routingDataSource" class="com.yhbc.datasourceT.RoutingDataSource">

<beans:property name="targetDataSources">

<beans:map key-type="java.lang.String">

<beans:entry key="defaultDataSource" value-ref="dataSource" />

</beans:map>

</beans:property>

<beans:property name="defaultTargetDataSource" ref="dataSource" ></beans:property>

</beans:bean>

<beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">

<!-- <beans:property name="dataSource" ref="dataSource" /> -->

<beans:property name="dataSource" ref="routingDataSource" />

<beans:property name="packagesToScan">

<beans:list>

<beans:value>com.yhbc.entity</beans:value>

</beans:list>

</beans:property>

<beans:property name="hibernateProperties">

<beans:value>

hibernate.dialect= org.hibernate.dialect.MySQLDialect

hibernate.show_sql=false

hibernate.format_sql=false

hibernate.query.substitutions=true 1, false 0

hibernate.jdbc.batch_size=20

hibernate.cache.use_query_cache=false

hibernate.cache.use_second_level_cache=true

hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory

hibernate.search.default.directory_provider=filesystem

hibernate.search.default.indexBase=d:\\index

</beans:value>

</beans:property>

</beans:bean>

4、测试,接下来在control中切换调用:

@RequestMapping(value = { "/hybd-findfunction.htm" }, produces = "text/html;charset=UTF-8")

    @ResponseBody

    public String findfunction(String functionUsername,String dbtype) {

    JSONObject jo=new JSONObject();

    log.info("-----------------------------/hybd-add.htm");

        try {

        //silverbox_backup

        /*Dbs.setDbType("backup");

        dynamicDataSource.determineTargetDataSource();*/

        if(dbtype!=null){

        //切换数据源,dbtype是数据库名称哦,这里的所有数据源默认都是相同的host,只是库的区别

        RoutingDataSourceContext.setThreadLocalDataSourceKey(dbtype);

        }

    System.out.println("sessionFactory==="+sessionFactory.toString());

        List<?> list=this.hYBDService.findFunction(functionUsername);

        jo.put("msg", "添加成功");

        jo.put("list", list);

        jo.put("success", true);

        } catch (Exception e) {

        jo.put("success", false);

          e.printStackTrace();

          log.error("error---hybd-add.htm-----:"+Utils.log4jDetail(e));

        }

        return jo.toJSONString();

    }

亲测通过哦,如果有用请多多支持哦

上一篇下一篇

猜你喜欢

热点阅读