spring简单分库分表

数据源获取工具

接口
package com.dlq.blog.datasource.interfaces;

import org.springframework.jdbc.core.JdbcTemplate;

/**
 * 数据源获取接口
 * @author donglq
 * @date 2017/10/4 23:20
 */
public interface IDatasourceGetter {

    JdbcTemplate getJdbcTemplate(String tablename);

}

实现
package com.dlq.blog.datasource;

import com.dlq.blog.datasource.interfaces.IDatasourceGetter;
import com.google.common.base.CharMatcher;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;

/**
 * 数据源获取实现
 * @author donglq
 * @date 2017/10/4 23:20
 */
public class DatasourceGetterImpl implements IDatasourceGetter{

    /**数据源**/
    private static JdbcTemplate[] templates;

    /**默认数据源**/
    private static JdbcTemplate defaultTemplate;

    private final static DatasourceIndexFunction DATASOURCE_INDEX_FUNCTION = new DatasourceIndexFunction();

    /**
     * 初始化
     * @param datasources 多数据源,有序
     * @param defaultdataSource
     */
    public DatasourceGetterImpl(DataSource[] datasources, DataSource defaultdataSource) {
        Preconditions.checkNotNull(datasources);
        Preconditions.checkNotNull(defaultdataSource);
        this.defaultTemplate = new JdbcTemplate(defaultdataSource);
        this.templates = new JdbcTemplate[datasources.length];
        for (int i = 0; i < datasources.length; i++) {
            this.templates[i] = new JdbcTemplate(datasources[i]);
        }
    }

    /**
     * 数据源获取类
     * 根据表名获取JdbcTemplate
     */
    private static class DatasourceIndexFunction implements Function<String, JdbcTemplate> {
        @Override
        public JdbcTemplate apply(String input) {
            if (Strings.isNullOrEmpty(input)) {
                return defaultTemplate;
            }
            try {
                int digit = Integer.parseInt(CharMatcher.DIGIT.retainFrom(input));
                return templates[digit % templates.length];
            } catch (NumberFormatException e) {
            }
            return defaultTemplate;
        }
    }

    /**
     * 缓存表名对应的库JdbcTemplate
     */
    private static final LoadingCache<String, JdbcTemplate> cache = CacheBuilder.newBuilder().maximumSize(1024).build(
            new CacheLoader<String, JdbcTemplate>() {
                @Override
                public JdbcTemplate load(String key) throws Exception {
                    return DATASOURCE_INDEX_FUNCTION.apply(key);
                }
            }
    );

    /**
     * 通过表名获取JdbcTemplate
     * @param tablename
     * @return
     */
    @Override
    public JdbcTemplate getJdbcTemplate(String tablename) {
        try {
            return cache.get(tablename);
        } catch (ExecutionException e) {
        }
        return defaultTemplate;
    }

}

测试

配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 引入配置文件 -->
    <bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:db.properties"/>
    </bean>
    <!--默认数据源-->
    <bean id="default" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${jdbc.mysql.user_03}"/>
        <property name="username" value="${jdbc.mysql.username}"/>
        <property name="password" value="${jdbc.mysql.password}"/>
    </bean>
    <!--配置多数据源-->
    <bean id="user_00" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${jdbc.mysql.user_00}"/>
        <property name="username" value="${jdbc.mysql.username}"/>
        <property name="password" value="${jdbc.mysql.password}"/>
    </bean>
    <bean id="user_01" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${jdbc.mysql.user_01}"/>
        <property name="username" value="${jdbc.mysql.username}"/>
        <property name="password" value="${jdbc.mysql.password}"/>
    </bean>
    <bean id="user_02" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${jdbc.mysql.user_02}"/>
        <property name="username" value="${jdbc.mysql.username}"/>
        <property name="password" value="${jdbc.mysql.password}"/>
    </bean>
    <bean id="user_03" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${jdbc.mysql.user_03}"/>
        <property name="username" value="${jdbc.mysql.username}"/>
        <property name="password" value="${jdbc.mysql.password}"/>
    </bean>
    <!--数据源获取类配置-->
    <bean id="datasourceGetter" class="com.dlq.blog.datasource.DatasourceGetterImpl">
        <constructor-arg index="0">
            <list>
                <ref bean="user_00"></ref>
                <ref bean="user_01"></ref>
                <ref bean="user_02"></ref>
                <ref bean="user_03"></ref>
            </list>
        </constructor-arg>
        <constructor-arg index="1" ref="default"/>
    </bean>
</beans>
测试方法
@Resource
IDatasourceGetter datasourceGetter;

public List<User> getByIdcard(String idcard) {
    //获取表明
    String tableName = new Function<String, String>() {
        @Override
        public String apply(String s) {
            String suffix = "";
            //共8张表,用身份证前6位计算位于哪张表
            int tableIndex = Integer.valueOf(s.substring(0, 6)) % 8;
            DecimalFormat df = new DecimalFormat();
            df.applyPattern("_00");
            suffix = df.format(tableIndex);
            return "user" + suffix;
        }
    }.apply(idcard);
    List<User> users = datasourceGetter.getJdbcTemplate(tableName).query("select * from " + tableName + " where idcard='" + idcard + "'", new RowMapper<User>() {
        @Nullable
        @Override
        public User mapRow(ResultSet rs, int rowNum) throws SQLException {
            System.out.println("idcard: " + rs.getString("idcard"));
            User user = new User();
            user.setId(rs.getInt("id"));
            user.setFirstname(rs.getString("firstname"));
            user.setLastname(rs.getString("lastname"));
            user.setIdcard(rs.getString("idcard"));
            user.setAddress(rs.getString("address"));
            return user;
        }
    });
    return users;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容