springboot+jpa+sharding-jdbc分表

1. 引入依赖:

<dependency>
            <groupId>com.dangdang</groupId>
            <artifactId>sharding-jdbc-core</artifactId>
            <version>1.5.4</version>
        </dependency>

2. 建立数据表:tabe_0,table_1,table_2...

3. 实现分表算法

import java.util.Collection;
import java.util.LinkedHashSet;

import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.SingleKeyTableShardingAlgorithm;
import com.google.common.collect.Range;

public final class JdbcSharingConfig implements SingleKeyTableShardingAlgorithm<Long> {
     
    /**
     * doEqualSharding =
     * @param tableNames 实际物理表名
     * @param shardingValue [logicTableName="t_order", columnName="order_id", value=20]
     * 
     *  select * from t_order from t_order where order_id = 11
     *          └── SELECT *  FROM t_order_1 WHERE order_id = 11
     *  select * from t_order from t_order where order_id = 44
     *          └── SELECT *  FROM t_order_0 WHERE order_id = 44
     *
     *  select * from t_order from t_order where order_id = 11
     *          └── SELECT *  FROM t_order_1 WHERE order_id = 11
     *  select * from t_order from t_order where order_id = 44
     *          └── SELECT *  FROM t_order_0 WHERE order_id = 44
     */
    public String doEqualSharding(final Collection<String> tableNames, final ShardingValue<Long> shardingValue) {
        
        int index = (int)(shardingValue.getValue() % 450);
        String indexStr = "";
        if(index >= 300)
            indexStr = "2";
        else if(index >= 150)
            indexStr = "1";
        else
            indexStr = "0";
        
        for (String each : tableNames) {
            if (each.endsWith(indexStr)) {
                return each;
            }
        }
        throw new IllegalArgumentException();
    }

    /**
     *  select * from t_order from t_order where order_id in (11,44)
     *          ├── SELECT *  FROM t_order_0 WHERE order_id IN (11,44)
     *          └── SELECT *  FROM t_order_1 WHERE order_id IN (11,44)
     *  select * from t_order from t_order where order_id in (11,13,15)
     *          └── SELECT *  FROM t_order_1 WHERE order_id IN (11,13,15)
     *  select * from t_order from t_order where order_id in (22,24,26)
     *          └──SELECT *  FROM t_order_0 WHERE order_id IN (22,24,26)
     */
    @Override
    public Collection<String> doInSharding(final Collection<String> tableNames, final ShardingValue<Long> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(tableNames.size());
        for (Long value : shardingValue.getValues()) {
            int index = (int)(value % 450);
            String indexStr = "";
            if(index >= 450)
                indexStr = "2";
            else if(index >= 300)
                indexStr = "1";
            else
                indexStr = "0";
            
            for (String tableName : tableNames) {
                if (tableName.endsWith(indexStr)) {
                    result.add(tableName);
                }
            }
        }
        return result;
    }
    /**
     *  select * from t_order from t_order where order_id between 10 and 20
     *          ├── SELECT *  FROM t_order_0 WHERE order_id BETWEEN 10 AND 20
     *          └── SELECT *  FROM t_order_1 WHERE order_id BETWEEN 10 AND 20
     */
    @Override
    public Collection<String> doBetweenSharding(final Collection<String> tableNames, final ShardingValue<Long> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(tableNames.size());
        Range<Long> range = shardingValue.getValueRange();
        for (Long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
            int index = (int)(i % 450);
            String indexStr = "";
            if(index >= 450)
                indexStr = "2";
            else if(index >= 300)
                indexStr = "1";
            else
                indexStr = "0";
            
            for (String each : tableNames) {
                if (each.endsWith(indexStr)) {
                    result.add(each);
                }
            }
        }
        return result;
    }

4. 配置类:

扫描二维码关注公众号,回复: 3961922 查看本文章

import com.alibaba.druid.pool.DruidDataSource;
import com.dangdang.ddframe.rdb.sharding.api.ShardingDataSourceFactory;
import com.dangdang.ddframe.rdb.sharding.api.rule.DataSourceRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.TableRule;
//import com.dangdang.ddframe.rdb.sharding.api.strategy.database.DatabaseShardingStrategy;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.TableShardingStrategy;
import com.mysql.jdbc.Driver;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;


@Configuration
public class DataSourceConfiguration {
    
    @Value("${database.name}")
    private String databaseName;
    
    @Value("${database.user}")
    private String username;
    
    @Value("${database.psw}")
    private String psw;
    
    
    @Bean
    public DataSource getDataSource() throws SQLException {
        return buildDataSource();
    }

    private DataSource buildDataSource() throws SQLException {
        // 设置分库映射
        Map<String, DataSource> dataSourceMap = new HashMap<>(2);
        // 添加两个数据库db0,db1到map里
        dataSourceMap.put("db0", createDataSource(databaseName, username, psw));
//        dataSourceMap.put("db1", createDataSource("db1"));
        // 设置默认db为db0,也就是为那些没有配置分库分表策略的指定的默认库
        // 如果只有一个库,也就是不需要分库的话,map里只放一个映射就行了,只有一个库时不需要指定默认库,但2个及以上时必须指定默认库,否则那些没有配置策略的表将无法操作数据
        DataSourceRule dataSourceRule = new DataSourceRule(dataSourceMap, "db0");

        // 设置分表映射,将table_0和table_1两个实际的表映射到table逻辑表
        // 0和1两个表是真实的表,table是个虚拟不存在的表,只是供使用。如查询所有数据就是select * from table就能查完0和1表的
        TableRule orderTableRule = TableRule.builder("table")
                .actualTables(Arrays.asList("table_0", "table_1", "table_2"))
                .dataSourceRule(dataSourceRule)
                .build();

        // 具体分库分表策略,按什么规则来分
        ShardingRule shardingRule = ShardingRule.builder()
                .dataSourceRule(dataSourceRule)
                .tableRules(Arrays.asList(orderTableRule))
//                .databaseShardingStrategy(new DatabaseShardingStrategy("id_table", new JdbcSharingConfig()))
                .tableShardingStrategy(new TableShardingStrategy("id_table", new JdbcSharingConfig())).build();

        DataSource dataSource = ShardingDataSourceFactory.createDataSource(shardingRule);

        return dataSource;
    }

    private static DataSource createDataSource(final String dataSourceName, final String username, final String psw) {
        // 使用druid连接数据库
        DruidDataSource result = new DruidDataSource();
        result.setDriverClassName(Driver.class.getName());
        result.setUrl(dataSourceName);
        result.setUsername(username);
        result.setPassword(psw);
        return result;
    }
}

猜你喜欢

转载自blog.csdn.net/jared_he2017/article/details/82800377
今日推荐