在本文中使用Spring Boot 2.4.1+MyBatis-plus+Druid+Sharding-JDBC+MySQL进行读写分离的案件讲解。
1、数据库准备
1、192.168.8.162 test1主
2、192.168.8.134 test1从
3、192.168.8.176 test1从
2、准备分表
DROP TABLE IF EXISTS `t_user_0`; CREATE TABLE `t_user_0` ( `id` int(10) NOT NULL, `name` varchar(50) NOT NULL, `sex` varchar(10) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `t_user_1`; CREATE TABLE `t_user_1` ( `id` int(10) NOT NULL, `name` varchar(50) NOT NULL, `sex` varchar(10) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `t_user_2`; CREATE TABLE `t_user_2` ( `id` int(10) NOT NULL, `name` varchar(50) NOT NULL, `sex` varchar(10) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `t_user_3`; CREATE TABLE `t_user_3` ( `id` int(10) NOT NULL, `name` varchar(50) NOT NULL, `sex` varchar(10) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3、上代码
1、pom.xml配置引入maven依赖
<properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <druid.version>1.1.9</druid.version> <mybatis-plus.version>3.1.1</mybatis-plus.version> <mybatis-plus-stater.version>3.1.2</mybatis-plus-stater.version> <lombok.version>1.16.18</lombok.version> <mybatisplus-spring-boot-starter.version>1.0.5</mybatisplus-spring-boot-starter.version> </properties> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</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> <!-- druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <!-- Mybatis-plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatisplus-spring-boot-starter</artifactId> <version>${mybatisplus-spring-boot-starter.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis-plus-stater.version}</version> </dependency> <!--shardingsphere数据分片、脱敏工具--> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.1.0</version> </dependency>
2、在application.yml中配置使用mybatis-plus及引用数据源及分表信息
spring: # 配置说明地址 https://test1.apache.org/document/legacy/4.x/document/cn/manual/sharding-jdbc/configuration/config-spring-boot/#%E6%95%B0%E6%8D%AE%E5%88%86%E7%89%87 shardingsphere: # 数据库 datasource: # 主库1 ,master数据库 master0: ### 数据源类别 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver url: jdbc:mysql://192.168.8.162:3306/test1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8 username: root password: root # 从库1 ,slave数据库 master0slave0: ### 数据源类别 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver url: jdbc:mysql://192.168.8.134:3306/test1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8 username: root password: root # 从库2 ,slave数据库 master0slave1: ### 数据源类别 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver url: jdbc:mysql://192.168.8.176:3306/test1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8 username: root password: root # 数据库的别名 names: master0,master0slave0,master0slave1 sharding: # 设置绑定表,用逗号分割 binding-tables: t_user master-slave-rules: ds0: name: ds0datasource # 查询时的负载均衡算法,目前有2种算法,round_robin(轮询)和random(随机), # 算法接口是io.shardingjdbc.core.api.algorithm.masterslave.MasterSlaveLoadBalanceAlgorithm。 # 实现类有RandomMasterSlaveLoadBalanceAlgorithm 和 RoundRobinMasterSlaveLoadBalanceAlgorithm。 load-balance-algorithm-type: round_robin # 主数据源名称 master-data-source-name: master0 slave-data-source-names: master0slave0, master0slave1 # 从数据源名称,多个用逗号隔开 tables: ### t_user分表配置 t_user: actual-data-nodes: ds0.t_user_$->{0..3} table-strategy: standard: precise-algorithm-class-name: com.demo.shardingjdbc.MyPreciseShardingAlgorithm sharding-column: id #### mybatis-plus ### mybatis-plus: # 如果是放在src/main/java目录下 classpath:/com/yourpackage/*/mapper/*Mapper.xml # 如果是放在resource目录 classpath:/mapper/*Mapper.xml mapper-locations: classpath:mapper/*.xml #实体扫描,多个package用逗号或者分号分隔 type-aliases-package: com.demo.shardingjdbc.entity configuration: map-underscore-to-camel-case: true cache-enabled: false #主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID"; global-config: db-config: id-type: auto #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断" field-strategy: not-empty #驼峰下划线转换 column-underline: true #逻辑删除配置 logic-delete-value: 0 logic-not-delete-value: 1 db-type: mysql #刷新mapper 调试神器 refresh: false
3、配置分表分片规则(结合application.yml)
package com.demo.shardingjdbc; import java.util.Collection; import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm; import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue; /** * 自定义实现 精准分片算法(PreciseShardingAlgorithm)接口 * 数据表table的精准分片 * @author hzy * */ public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Integer> { @Override public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Integer> shardingValue) { for (String tableName : availableTargetNames) { if (tableName.endsWith(shardingValue.getValue() % 4 + "")) { return tableName; } } throw new IllegalArgumentException(); } }
4、mybatis-plus操作数据库配置
User.java
package com.demo.shardingjdbc.entity; import java.io.Serializable; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; /** * @Description: (User)实体类 * @Version 1.0 */ @Data @TableName("t_user") public class User implements Serializable { private static final long serialVersionUID = 358157380505039579L; /** * 用户id */ @TableId(type = IdType.INPUT) private Integer id; /** * 用户名称 */ private String name; /** * 性别 */ private String sex; }
mapper
package com.demo.shardingjdbc.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.demo.shardingjdbc.entity.User; /** * (t_user)表数据库访问层 * */ public interface UserMapper extends BaseMapper<User> { }
5、mybatis-plus配置MybatisPlusConfig
package com.demo.shardingjdbc.config; import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; /** * @Description: */ //Spring boot方式 @EnableTransactionManagement @Configuration //扫描的mapper文件路径 @MapperScan(value = "com.demo.shardingjdbc.mapper") public class MybatisPlusConfig { /** * 分页插件 */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } }
6、service层
package com.demo.shardingjdbc.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.demo.shardingjdbc.entity.User; import com.demo.shardingjdbc.mapper.UserMapper; import com.demo.shardingjdbc.service.UserService; @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public List<User> selectList() { QueryWrapper<User> wrapper = new QueryWrapper<User>(); wrapper.orderByAsc("id"); List<User> users = userMapper.selectList(wrapper); return users; } @Override public int insert(User user) { return userMapper.insert(user); } }
7、controller控制层
package com.demo.shardingjdbc.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.demo.shardingjdbc.entity.User; import com.demo.shardingjdbc.service.UserService; import lombok.extern.slf4j.Slf4j; /** * @ClassName TestController * @Description TestController * @Version */ @RestController @Slf4j public class UserController { @Autowired private UserService userService; /** * 用户列表 * * @return */ @RequestMapping("/userList") public List<User> userList() { log.info("********TestController userList()"); List<User> users = userService.selectList(); return users; } /** * 保存用户 * * @return */ @GetMapping("/add") public Object add() { int num = 0; for (int i = 1; i <= 150; i++) { User user = new User(); user.setId(i); user.setName("hzy" + (i)); String sex = (i % 2 == 0) ? "男" : "女"; user.setSex(sex); int resutl = userService.insert(user); log.info("insert:" + user.toString() + " result:" + resutl); num = num + resutl; } return num; } }
完成。在浏览器上执行localhost:8080/add,然后去数据库中查询,可以看到t_user_0、t_user_1、t_user_2、t_user_3分别插入了数据。
然后访问localhost:8080/userList,可以查询数据库中四个表中的所有数据。可见Sharding-JDBC在插入数据的时候,根据数据分表策略,将数据存储在不同的表中,查询的时候将数据库从多个表中查询并聚合.