sharding jdbc分库分表实现源码分享

java1234

共 8020字,需浏览 17分钟

 ·

2020-09-16 07:37

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

66套java从入门到精通实战课程分享 

  • 背景

最近在研究Mysql的分库分表,前面的博客已经详细介绍了分库分表!

由于sharding-jdbc是不支持动态进行建库的SQL,那么就需要一次把需要的数据库和数据表都建好

  • 建库、建表

考虑到这只是一个测试的demo,所以,只建了两个库和两个表

  1. CREATE TABLE `t_order_0` (
     `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',
     `order_id` VARCHAR(32) NULL DEFAULT NULL COMMENT '顺序编号',
     `user_id` VARCHAR(32) NULL DEFAULT NULL COMMENT '用户编号',
     `userName` VARCHAR(32) NULL DEFAULT NULL COMMENT '用户名',
     `passWord` VARCHAR(32) NULL DEFAULT NULL COMMENT '密码',
     `nick_name` VARCHAR(32) NULL DEFAULT NULL,
  • SpringBoot+Mybatis+sharding-jdbc框架搭建(pom文件)


  1.         
                org.springframework.boot
                spring-boot-starter
            

            
                org.springframework.boot
                spring-boot-starter-test
                test
            

            
                org.springframework.boot
                spring-boot-starter-web
            

            
                org.mybatis.spring.boot
                mybatis-spring-boot-starter
                1.1.1
            

            
                mysql
                mysql-connector-java
            

            
                org.springframework.boot
                spring-boot-devtools
                true
            

     
            
                org.projectlombok
                lombok
            

     
            
            
                com.dangdang
                sharding-jdbc-core
                1.5.4
            

        

  • 配置文件

  1. mybatis.config-locations=classpath:mybatis/mybatis-config.xml
     
    #datasource
    spring.devtools.remote.restart.enabled=false
     
    #data source1
    spring.datasource.test1.driverClassName=com.mysql.jdbc.Driver
    spring.datasource.test1.jdbcUrl=jdbc:mysql://127.0.0.1:3306/test_msg1?serverTimezone=UTC
    spring.datasource.test1.username=root
    spring.datasource.test1.password=123456
     
    #data source2
    spring.datasource.test2.driverClassName=com.mysql.jdbc.Driver
    spring.datasource.test2.jdbcUrl=jdbc:mysql://127.0.0.1:3306/test_msg2?serverTimezone=UTC
    spring.datasource.test2.username=root
    spring.datasource.test2.password=123456
  • 启动文件

  1. @SpringBootApplication
    @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) //排除DataSourceConfiguratrion
    @EnableTransactionManagement(proxyTargetClass = true)   //开启事物管理功能
    public class ShardingJdbcApplication {
        
        public static void main(String[] args) {
            SpringApplication.run(ShardingJdbcApplication.class, args);
        }
    }
  • 实体类(Data注解可免去set/get方法)

  1. @Data
    public class User {
     
        private Long id;
        private Long order_id;
        private Long user_id;
        private String userName;
        private String passWord;
        private String nickName;
    }
  • Service层

  1. @Slf4j
    @Service
    public class UserService {
     
        @Resource
        private UserMapper userMapper;
     
        public void insert(User user) {
            userMapper.insert(user);
        }
    }
  • Mapper层

  1. public interface UserMapper {
     
        void insert(User user);
    }
  • 数据源配置和Mybatis配置和分库分表规则(重要)

这里,我们是将多个数据源交给sharding-jdbc进行管理,并且有默认的数据源,当没有设置分库分表规则的时候就可以使用默认的数据源

分表:user_id%2 = 0的数据存储到test_msg1,为1的存储到test_msg0

分表:order_id%2 = 0的数据存储到t_order_0,为1的存储到t_order_1

  1. /**
     * @Auther: Tinko
     * @Date: 2018/12/19 16:27
     * @Description: 数据源配置和Mybatis配置和分库分表规则
     */
    @Configuration
    @MapperScan(basePackages = "com.example.shardingjdbc.mapper", sqlSessionTemplateRef  = "test1SqlSessionTemplate")
    public class DataSourceConfig {
     
        /**
         * 配置数据源0,数据源的名称最好要有一定的规则,方便配置分库的计算规则
         * @return
         */
        @Bean(name="dataSource0")
        @ConfigurationProperties(prefix = "spring.datasource.test1")
        public DataSource dataSource0(){
            return DataSourceBuilder.create().build();
        }
        /**
         * 配置数据源1,数据源的名称最好要有一定的规则,方便配置分库的计算规则
         * @return
         */
        @Bean(name="dataSource1")
        @ConfigurationProperties(prefix = "spring.datasource.test2")
        public DataSource dataSource1(){
            return DataSourceBuilder.create().build();
        }
     
        /**
         * 配置数据源规则,即将多个数据源交给sharding-jdbc管理,并且可以设置默认的数据源,
         * 当表没有配置分库规则时会使用默认的数据源
         * @param dataSource0
         * @param dataSource1
         * @return
         */
        @Bean
        public DataSourceRule dataSourceRule(@Qualifier("dataSource0") DataSource dataSource0,
                                             @Qualifier("dataSource1") DataSource dataSource1){
            Map dataSourceMap = new HashMap<>(); //设置分库映射
            dataSourceMap.put("dataSource0", dataSource0);
            dataSourceMap.put("dataSource1", dataSource1);
            return new DataSourceRule(dataSourceMap, "dataSource0"); //设置默认库,两个库以上时必须设置默认库。默认库的数据源名称必须是dataSourceMap的key之一
        }
     
        /**
         * 配置数据源策略和表策略,具体策略需要自己实现
         * @param dataSourceRule
         * @return
         */
        @Bean
        public ShardingRule shardingRule(DataSourceRule dataSourceRule){
            //具体分库分表策略
            TableRule orderTableRule = TableRule.builder("t_order")
                    .actualTables(Arrays.asList("t_order_0""t_order_1"))
                    .tableShardingStrategy(new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm()))
                    .dataSourceRule(dataSourceRule)
                    .build();
     
            //绑定表策略,在查询时会使用主表策略计算路由的数据源,因此需要约定绑定表策略的表的规则需要一致,可以一定程度提高效率
            List bindingTableRules = new ArrayList();
            bindingTableRules.add(new BindingTableRule(Arrays.asList(orderTableRule)));
            return ShardingRule.builder()
                    .dataSourceRule(dataSourceRule)
                    .tableRules(Arrays.asList(orderTableRule))
                    .bindingTableRules(bindingTableRules)
                    .databaseShardingStrategy(new DatabaseShardingStrategy("user_id", new ModuloDatabaseShardingAlgorithm()))
                    .tableShardingStrategy(new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm()))
                    .build();
        }
     
        /**
         * 创建sharding-jdbc的数据源DataSource,MybatisAutoConfiguration会使用此数据源
         * @param shardingRule
         * @return
         * @throws SQLException
         */
        @Bean(name="dataSource")
        public DataSource shardingDataSource(ShardingRule shardingRule) throws SQLException {
            return ShardingDataSourceFactory.createDataSource(shardingRule);
        }
     
        /**
         * 需要手动配置事务管理器
         * @param dataSource
         * @return
         */
        @Bean
        public DataSourceTransactionManager transactitonManager(@Qualifier("dataSource") DataSource dataSource){
            return new DataSourceTransactionManager(dataSource);
        }
     
        @Bean(name = "test1SqlSessionFactory")
        @Primary
        public SqlSessionFactory testSqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
            SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
            bean.setDataSource(dataSource);
            bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/*.xml"));
            return bean.getObject();
        }
     
        @Bean(name = "test1SqlSessionTemplate")
        @Primary
        public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
            return new SqlSessionTemplate(sqlSessionFactory);
        }
    }
  • 分库规则

  • /**
     * @Auther: Tinko
     * @Date: 2018/12/19 16:31
     * @Description: 分库规则
     */
    public class ModuloDatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm {
     
        @Override
        public String doEqualSharding(Collection databaseNames, ShardingValue shardingValue) {
            for (String each : databaseNames) {
                if (each.endsWith(Long.parseLong(shardingValue.getValue().toString()) % 2 + "")) {
                    return each;
                }
            }
            throw new IllegalArgumentException();
        }
     
        @Override
        public Collection doInSharding(Collection databaseNames, ShardingValue shardingValue) {
            Collection result = new LinkedHashSet<>(databaseNames.size());
            for (Long value : shardingValue.getValues()) {
                for (String tableName : databaseNames) {
                    if (tableName.endsWith(value % 2 + "")) {
                        result.add(tableName);
                    }
                }
            }
            return result;
        }
     
        @Override
        public Collection doBetweenSharding(Collection databaseNames, ShardingValue shardingValue) {
            Collection result = new LinkedHashSet<>(databaseNames.size());
            Range range = (Range) shardingValue.getValueRange();
            for (Long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
                for (String each : databaseNames) {
                    if (each.endsWith(i % 2 + "")) {
                        result.add(each);
                    }
                }
            }
            return result;
        }

  • 分表规则

  • /**
     * @Auther: Tinko
     * @Date: 2018/12/19 16:30
     * @Description: 分表规则
     */
    public class ModuloTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm {
     
        @Override
        public String doEqualSharding(Collection tableNames, ShardingValue shardingValue) {
            for (String each : tableNames) {
                if (each.endsWith(shardingValue.getValue() % 2 + "")) {
                    return each;
                }
            }
            throw new IllegalArgumentException();
        }
     
        @Override
        public Collection doInSharding(Collection tableNames, ShardingValue shardingValue) {
            Collection result = new LinkedHashSet<>(tableNames.size());
            for (Long value : shardingValue.getValues()) {
                for (String tableName : tableNames) {
                    if (tableName.endsWith(value % 2 + "")) {
                        result.add(tableName);
                    }
                }
            }
            return result;
        }
     
        @Override
        public Collection doBetweenSharding(Collection tableNames, ShardingValue shardingValue) {
            Collection result = new LinkedHashSet<>(tableNames.size());
            Range range = (Range) shardingValue.getValueRange();
            for (Long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
                for (String each : tableNames) {
                    if (each.endsWith(i % 2 + "")) {
                        result.add(each);
                    }
                }
            }
            return result;
        }
    }
  • 与Mysql交互的配置的文件

  • "1.0" encoding="UTF-8" ?>
    "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    "com.example.shardingjdbc.mapper.UserMapper" >
     
        "Base_Column_List" >
            id, userName, passWord, user_sex, nick_name
        
     
        "insert" parameterType="com.example.shardingjdbc.entity.User" >
            INSERT INTO
            t_order
            (order_id,user_id,userName,passWord)
            VALUES
            (#{order_id},#{user_id},#{userName}, #{passWord})
        
     

git传送门

https://github.com/MissDistin/sharding-jdbc-1

然后,测试可行!!!



版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:

https://blog.csdn.net/a992795427/article/details/85102918



粉丝福利:108本java从入门到大神精选电子书领取

???

?长按上方锋哥微信二维码 2 秒
备注「1234」即可获取资料以及
可以进入java1234官方微信群



感谢点赞支持下哈 


浏览 34
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报