shardingjdbc 入门demo(jdbc+mybatis+springboot)

shardingjdbc 入门demo(jdbc+mybatis+springboot,同库分表)

一.使用场景

本人有两张用户表,想根据id的奇偶进行分表

test_user_1 、test_user_2

二.代码示例

框架使用的是mybatis+plus

全局pom

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.9.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.git</groupId>
    <artifactId>mybatis-sharding</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mybatis-sharding</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.0</version>
        </dependency>

        <!-- 这个巨坑,官网的找不到 -->
        <!--<dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core</artifactId>
            <version>4.0.0</version>
        </dependency>-->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-core</artifactId>
            <version>4.1.1</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.1 jdbc使用demo

/**
 * @author authorZhao
 * @since 2020-09-22
 */
@Slf4j
public class JdbcTest {

    public static Map<String,DataSource> dataSourceMap=new ConcurrentHashMap<>();
    static{
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:306/test_user?characterEncoding=utf8&serverTimezone=UTC&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useSSL=false");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSourceMap.put("test_user",dataSource);
    }

    @Test
    public void test1(){
//分表规则有几个建立几个,表名  后面库名.表名字
        TableRuleConfiguration orderTableRuleConfig = new TableRuleConfiguration("test_user_","test.test_user_{}");

        PreciseShardingAlgorithm preciseShardingAlgorithm = new PreciseShardingAlgorithm() {
            @Override
            public String doSharding(Collection availableTargetNames, PreciseShardingValue shardingValue) {
                //拿到id,根据id最后一个数字分表
                String id = ((String) shardingValue.getValue());
                String lastNum = id.substring(id.length() - 1);
                String tableName =  shardingValue.getLogicTableName()+((Long.valueOf(lastNum)%2) ==0L?2:1);
                return tableName;
            }
        };

        // 配置分表策略
        orderTableRuleConfig.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("id",preciseShardingAlgorithm));

        // 配置分片规则
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTableRuleConfigs().add(orderTableRuleConfig);

        HikariDataSource dataSource = new HikariDataSource();
        String url = dataSourceProperties.getUrl();

        //数据源
        dataSource.setJdbcUrl(url);
        dataSource.setUsername(dataSourceProperties.getUsername());
        dataSource.setPassword(dataSourceProperties.getPassword());
        dataSource.setDriverClassName(dataSourceProperties.getDriverClassName());
        String dataBase = url.substring(url.lastIndexOf("/")+1, url.indexOf("?"));
        //以数据库名字为key
        dataSourceMap.put(dataBase,dataSource);

        Properties props=new Properties();
        //打印sql
        props.put("sql.show", "true");
        
        // 获取数据源对象
        //javax.sql.DataSource
        try {
            DataSource dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig,  new Properties());
            querySql(dataSource);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

    }

    private void querySql(DataSource dataSource) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try{
            connection = dataSource.getConnection();
            //实际执行的时候test_user_会被替换成你设置的表明和库名
            preparedStatement = connection.prepareStatement("select * from test_user_ where id= '2044501603703006837335334921'");
            //preparedStatement.setString(1,"2044501603703006837335334921");
            ResultSet resultSet = preparedStatement.executeQuery();
            Map<String,Object> map = new HashMap();
            int i = 1;
            while(resultSet.next()){
                System.out.println("resultSet.getString(i) = " + resultSet.getString(i));
                map.put(resultSet.getString(i),resultSet.getString(i));
                i++;
            }
            System.out.println(map);
        }catch (Exception e){
            log.error("sql执行错误",e);
        }finally {
            try {
                if(preparedStatement!=null)preparedStatement.close();
                if(connection!=null)connection.close();
            }catch (Exception e){
                log.error("资源释放错误",e);
            }
        }



    }

}

测试略

2.2mybats使用方式

2.2.1.实体类和接口
@Data
@Accessors(chain = true)
@TableName("test_user_")
class BugUser {//为什么叫bug,因为sharding不支持jdk8的LocalDateTime
    @TableId(type = IdType.ASSIGN_ID)
    private String id;
    private String name;
    private String nickName;
    private String password;
    private Date createTime;
    private Date updateTime;
    private String tel;
    private Integer age;

}

@Mapper
interface BugUserMapper extends BaseMapper<BugUser> {

}
2.2.2.测试类和启动类
//测试类
@SpringBootTest(classes = BugMybatisShardingApplication.class)
class MybatisPlusTests {

    @Autowired
    private BugUserMapper userMapper;

    @Test
    void insert() {
        BugUser user1 = userMapper.selectById("1308364076644413441");
        BugUser user2 = userMapper.selectById("1308364076644413442");
        List<BugUser> bugUsers = userMapper.selectList(new QueryWrapper<BugUser>().eq("name", "张三"));
        System.out.println(bugUsers);
        System.out.println(user1);
        System.out.println(user2);
    }
}

//启动类
@SpringBootApplication
//为了不影响其他测试,这里手动导入
@Import(LocalDataSourceConfig.class)
//正常的mapper扫描,扫描的是上面的mapper
@MapperScan("com.git.shard.shard")
class BugMybatisShardingApplication {

    public static void main(String[] args) {   SpringApplication.run(com.git.MybatisShardingApplication.class, args);
    }

}

2.2.3.yml配置文件
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&serverTimezone=UTC&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver
com:
  git:
    dataSource: local
logging:
  level:
    com:
      git:
        shard:
          shard: DEBUG
          mapper: DEBUG #这俩设置mybatis的日志
2.2.4.datasource配置文件
/**
 * @author authorZhao
 * @since 2020-10-27
 */

@Configuration
@ConditionalOnMissingBean(DataSource.class)
@Slf4j
@ConditionalOnProperty(name = {"com.git.dataSource"}, havingValue = "local")
public class LocalDataSourceConfig {

    @Autowired
    private DataSourceProperties dataSourceProperties;

    public static final Map<String,DataSource> dataSourceMap=new ConcurrentHashMap<>();

    @Bean
    DataSource dataSource(){

        //分表规则有几个建立几个,表名  后面库名.表名字
        TableRuleConfiguration orderTableRuleConfig = new TableRuleConfiguration("test_user_","test.test_user_{}");

        PreciseShardingAlgorithm preciseShardingAlgorithm = new PreciseShardingAlgorithm() {
            @Override
            public String doSharding(Collection availableTargetNames, PreciseShardingValue shardingValue) {
                //拿到id,根据id最后一个数字分表
                String id = ((String) shardingValue.getValue());
                String lastNum = id.substring(id.length() - 1);
                String tableName =  shardingValue.getLogicTableName()+((Long.valueOf(lastNum)%2) ==0L?2:1);
                return tableName;
            }
        };

        // 配置分表策略
        orderTableRuleConfig.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("id",preciseShardingAlgorithm));

        // 配置分片规则
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTableRuleConfigs().add(orderTableRuleConfig);

        HikariDataSource dataSource = new HikariDataSource();
        String url = dataSourceProperties.getUrl();

        //数据源
        dataSource.setJdbcUrl(url);
        dataSource.setUsername(dataSourceProperties.getUsername());
        dataSource.setPassword(dataSourceProperties.getPassword());
        dataSource.setDriverClassName(dataSourceProperties.getDriverClassName());
        String dataBase = url.substring(url.lastIndexOf("/")+1, url.indexOf("?"));
        //以数据库名字为key
        dataSourceMap.put(dataBase,dataSource);

        Properties props=new Properties();
        //打印sql
        props.put("sql.show", "true");

        DataSource dataSource1 = null;
        try {
            dataSource1 =  ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig,  props);
        } catch (SQLException throwables) {
            dataSource1 = dataSource;
            log.warn("sharding 配置失败,分表无效");

        }
        return dataSource1;
    }
}

2.2.5测试结果:
2020-10-30 16:22:30.486 DEBUG 7284 --- [           main] c.g.s.shard.BugUserMapper.selectById     : ==>  Preparing: SELECT id,name,nick_name,password,create_time,update_time,tel,age FROM test_user_ WHERE id=?
2020-10-30 16:22:30.508 DEBUG 7284 --- [           main] c.g.s.shard.BugUserMapper.selectById     : ==> Parameters: 1308364076644413441(String)
2020-10-30 16:22:30.846  INFO 7284 --- [           main] ShardingSphere-SQL                       : Logic SQL: SELECT id,name,nick_name,password,create_time,update_time,tel,age FROM test_user_ WHERE id=? 
2020-10-30 16:22:30.846  INFO 7284 --- [           main] ShardingSphere-SQL                       : SQLStatement: SelectStatementContext(super=CommonSQLStatementContext(sqlStatement=org.apache.shardingsphere.sql.parser.sql.statement.dml.SelectStatement@f6cde7e, tablesContext=org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext@ff8e36d), tablesContext=org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext@ff8e36d, projectionsContext=ProjectionsContext(startIndex=7, stopIndex=64, distinctRow=false, projections=[ColumnProjection(owner=null, name=id, alias=Optional.empty), ColumnProjection(owner=null, name=name, alias=Optional.empty), ColumnProjection(owner=null, name=nick_name, alias=Optional.empty), ColumnProjection(owner=null, name=password, alias=Optional.empty), ColumnProjection(owner=null, name=create_time, alias=Optional.empty), ColumnProjection(owner=null, name=update_time, alias=Optional.empty), ColumnProjection(owner=null, name=tel, alias=Optional.empty), ColumnProjection(owner=null, name=age, alias=Optional.empty)]), groupByContext=org.apache.shardingsphere.sql.parser.binder.segment.select.groupby.GroupByContext@116b0b32, orderByContext=org.apache.shardingsphere.sql.parser.binder.segment.select.orderby.OrderByContext@4f22fd5d, paginationContext=org.apache.shardingsphere.sql.parser.binder.segment.select.pagination.PaginationContext@26d445e9, containsSubquery=false)
2020-10-30 16:22:30.846  INFO 7284 --- [           main] ShardingSphere-SQL                       : Actual SQL: test ::: SELECT id,name,nick_name,password,create_time,update_time,tel,age FROM test_user_1 WHERE id=?  ::: [1308364076644413441]
2020-10-30 16:22:30.889 DEBUG 7284 --- [           main] c.g.s.shard.BugUserMapper.selectById     : <==      Total: 1
2020-10-30 16:22:30.898 DEBUG 7284 --- [           main] c.g.s.shard.BugUserMapper.selectById     : ==>  Preparing: SELECT id,name,nick_name,password,create_time,update_time,tel,age FROM test_user_ WHERE id=?
2020-10-30 16:22:30.899 DEBUG 7284 --- [           main] c.g.s.shard.BugUserMapper.selectById     : ==> Parameters: 1308364076644413442(String)
2020-10-30 16:22:30.900  INFO 7284 --- [           main] ShardingSphere-SQL                       : Logic SQL: SELECT id,name,nick_name,password,create_time,update_time,tel,age FROM test_user_ WHERE id=? 
2020-10-30 16:22:30.900  INFO 7284 --- [           main] ShardingSphere-SQL                       : SQLStatement: SelectStatementContext(super=CommonSQLStatementContext(sqlStatement=org.apache.shardingsphere.sql.parser.sql.statement.dml.SelectStatement@f6cde7e, tablesContext=org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext@51c6e775), tablesContext=org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext@51c6e775, projectionsContext=ProjectionsContext(startIndex=7, stopIndex=64, distinctRow=false, projections=[ColumnProjection(owner=null, name=id, alias=Optional.empty), ColumnProjection(owner=null, name=name, alias=Optional.empty), ColumnProjection(owner=null, name=nick_name, alias=Optional.empty), ColumnProjection(owner=null, name=password, alias=Optional.empty), ColumnProjection(owner=null, name=create_time, alias=Optional.empty), ColumnProjection(owner=null, name=update_time, alias=Optional.empty), ColumnProjection(owner=null, name=tel, alias=Optional.empty), ColumnProjection(owner=null, name=age, alias=Optional.empty)]), groupByContext=org.apache.shardingsphere.sql.parser.binder.segment.select.groupby.GroupByContext@372841d2, orderByContext=org.apache.shardingsphere.sql.parser.binder.segment.select.orderby.OrderByContext@6c8d638a, paginationContext=org.apache.shardingsphere.sql.parser.binder.segment.select.pagination.PaginationContext@117069f2, containsSubquery=false)
2020-10-30 16:22:30.900  INFO 7284 --- [           main] ShardingSphere-SQL                       : Actual SQL: test ::: SELECT id,name,nick_name,password,create_time,update_time,tel,age FROM test_user_2 WHERE id=?  ::: [1308364076644413442]
2020-10-30 16:22:30.902 DEBUG 7284 --- [           main] c.g.s.shard.BugUserMapper.selectById     : <==      Total: 1
BugUser(id=1308364076644413441, name=张三, nickName=张三, password=123456, createTime=Wed Sep 23 03:14:38 CST 2020, updateTime=Wed Sep 23 03:14:38 CST 2020, tel=15674589456, age=18)
BugUser(id=1308364076644413442, name=李四, nickName=李四, password=123456, createTime=Wed Sep 23 03:14:38 CST 2020, updateTime=Wed Sep 23 03:14:38 CST 2020, tel=15674589456, age=18)

3.总结

1.sharding使用方法其实就是配置一些dataSource,与你使用的orm框架无关(前提是你必须使用jdbc),并且配置一些策略

2.对于没有分表的字段用来查询会报错大家可以自试一下

3.从官网上得知sharding的原理是jdbc代理

4.完!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值