Spring Boot2.0.3 Mybatis Sharding-jdbc3.X集成实现数据库的读写分离(二)-项目实现
上一篇文章,我们实现了Mysql的主从配置。并且配置了2个库,进行主从同步db0,db1。如果对主从配置不清楚的可以查看上一篇博客https://blog.csdn.net/zhuwei_clark/article/details/82898093。
这篇文章,主要讲解的是怎么使用Sharding-jdbc3.x实现数据库的读写分离。
官网地址:http://shardingsphere.io/index_zh.html
这里使用的3.X版本。POM文件配置
[code] <dependency> <groupId>io.shardingsphere</groupId> <artifactId>sharding-jdbc</artifactId> <version>3.0.0.M3</version> </dependency>
使用的是Spring boo 2.0.3 POM文件配置
[code] <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
ORM采用的是Mybatis,POM文件配置
[code] <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency>
application.yml文件配置如下
[code]server: port: 9090 spring: application: name: vts_sc_sharding_mybatis #sharding-jdbc的配置 sharding.jdbc: data-sources: ds_master: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://XX:3306/db1 username: daxian password: zhudaxian;.,68NB ds_slave_0: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://XX2:3306/db0 username: daxian password: zhudaxian;.,68NB master-slave-rule: name: ds_ms master-data-source-name: ds_master slave-data-source-names: ds_slave_0 load-balance-algorithm-type: round_robin props: sql.show: true #mybatis的配置 mybatis: config-location: classpath:mybatis/config.xml mapper-locations: - classpath:mybatis/mappers/*.xml
这里我为了验证数据确实读写分库,采用的不是对应的主从库,这里采用的主库是master机器的db1,从库是Slave机器的db0,也就是避免了mysql自身的主从机制复制数据。
使用Sharding配置数据源:
读取配置内容。
[code]@Data @ConfigurationProperties(prefix = "sharding.jdbc") public class ShardingMasterSlaveConfig { private Map<String, DruidDataSource> dataSources = new HashMap<>(); private MasterSlaveRuleConfiguration masterSlaveRule; }
配置数据源:
[code]@Slf4j @Configuration @EnableConfigurationProperties(ShardingMasterSlaveConfig.class) @ConditionalOnProperty({"sharding.jdbc.data-sources.ds_master.url", "sharding.jdbc.master-slave-rule.master-data-source-name"}) public class ShardingDataSourceConfig { @Autowired(required = false) private ShardingMasterSlaveConfig shardingMasterSlaveConfig; @Bean("dataSource") public DataSource masterSlaveDataSource() throws SQLException { shardingMasterSlaveConfig.getDataSources().forEach((k, v) -> configDataSource(v)); Map<String, DataSource> dataSourceMap = Maps.newHashMap(); dataSourceMap.putAll(shardingMasterSlaveConfig.getDataSources()); DataSource dataSource = MasterSlaveDataSourceFactory.createDataSource(dataSourceMap, shardingMasterSlaveConfig.getMasterSlaveRule(), new HashMap<String, Object>(), new Properties()); log.info("masterSlaveDataSource config complete"); return dataSource; } private void configDataSource(DruidDataSource druidDataSource) { druidDataSource.setMaxActive(20); druidDataSource.setInitialSize(1); druidDataSource.setMaxWait(60000); druidDataSource.setMinIdle(1); druidDataSource.setTimeBetweenEvictionRunsMillis(60000); druidDataSource.setMinEvictableIdleTimeMillis(300000); druidDataSource.setValidationQuery("select 'x'"); druidDataSource.setTestWhileIdle(true); druidDataSource.setTestOnBorrow(false); druidDataSource.setTestOnReturn(false); druidDataSource.setPoolPreparedStatements(true); druidDataSource.setMaxOpenPreparedStatements(20); druidDataSource.setUseGlobalDataSourceStat(true); try { druidDataSource.setFilters("stat,wall,slf4j"); } catch (SQLException e) { log.error("druid configuration initialization filter", e); } } }
Mybatis配置
resources文件下面新建mybatis文件,在mybatis文件下新建mappers文件夹。
在mybatis文件下配置mybatis的配置文件,这里注意用了配置文件,就不能再application里面配置configlcation属性。
[code]<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <!--配置命名规则--> <setting name="mapUnderscoreToCamelCase" value="true" /> </settings> <typeAliases> <typeAlias alias="Integer" type="java.lang.Integer" /> <typeAlias alias="Long" type="java.lang.Long" /> <typeAlias alias="HashMap" type="java.util.HashMap" /> <typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" /> <typeAlias alias="ArrayList" type="java.util.ArrayList" /> <typeAlias alias="LinkedList" type="java.util.LinkedList" /> </typeAliases> </configuration>
配置启动类
[code]@SpringBootApplication @MapperScan("com.vipcode.vts.dao") public class Application { public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } }
mybatis支持全注解方式和XML配置
全注解配置
[code]@Mapper public interface VTSUserAnnotation { @Insert("INSERT INTO vts_user(pk_user,userName,user_password,user_code) VALUES (#{pkUser},#{username},#{userPassword},#{userCode})") @Results({ @Result(column = "userName",property = "username"), }) int insert(VTSUser record); @Select("SELECT * FROM vts_user WHERE pk_user=#{pkUser}") @Results({ @Result(column = "userName",property = "username"), }) VTSUser selectByPrimaryKey(String pkUser); }
使用注解方式配置的话,最好是设置驼峰命令规则。需要使用@Mapper
XML配置
[code] @Repository("vtsUserMapper") public interface VTSUserMapper { int deleteByPrimaryKey(String pkUser); int insert(VTSUser record); int insertSelective(VTSUser record); VTSUser selectByPrimaryKey(String pkUser); int updateByPrimaryKeySelective(VTSUser record); int updateByPrimaryKey(VTSUser record); }
这里需要把接口托管给Spring,XML内容如下,是通过工具映射生成的。
[code]<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.vipcode.vts.dao.VTSUserMapper"> <resultMap id="BaseResultMap" type="com.vipcode.vts.entity.VTSUser"> <id column="pk_user" jdbcType="CHAR" property="pkUser" /> <result column="dr" jdbcType="INTEGER" property="dr" /> <result column="use_status" jdbcType="INTEGER" property="useStatus" /> <result column="create_date" jdbcType="CHAR" property="createDate" /> <result column="user_code" jdbcType="VARCHAR" property="userCode" /> <result column="user_password" jdbcType="VARCHAR" property="userPassword" /> <result column="userName" jdbcType="VARCHAR" property="username" /> <result column="user_sex" jdbcType="INTEGER" property="userSex" /> <result column="pk_status" jdbcType="VARCHAR" property="pkStatus" /> <result column="user_picture" jdbcType="VARCHAR" property="userPicture" /> <result column="regist_date" jdbcType="CHAR" property="registDate" /> <result column="login_status" jdbcType="INTEGER" property="loginStatus" /> <result column="login_platform" jdbcType="INTEGER" property="loginPlatform" /> <result column="login_deivce_code" jdbcType="VARCHAR" property="loginDeivceCode" /> <result column="is_first" jdbcType="INTEGER" property="isFirst" /> <result column="openID" jdbcType="VARCHAR" property="openid" /> <result column="weixin_url" jdbcType="VARCHAR" property="weixinUrl" /> <result column="weixin_name" jdbcType="VARCHAR" property="weixinName" /> <result column="bind_tag" jdbcType="VARCHAR" property="bindTag" /> <result column="bind_date" jdbcType="CHAR" property="bindDate" /> <result column="mac_address" jdbcType="VARCHAR" property="macAddress" /> <result column="ip_address" jdbcType="VARCHAR" property="ipAddress" /> <result column="AccessKey" jdbcType="VARCHAR" property="accesskey" /> <result column="SecretKey" jdbcType="VARCHAR" property="secretkey" /> </resultMap> <sql id="Base_Column_List"> pk_user, dr, use_status, create_date, user_code, user_password, userName, user_sex, pk_status, user_picture, regist_date, login_status, login_platform, login_deivce_code, is_first, openID, weixin_url, weixin_name, bind_tag, bind_date, mac_address, ip_address, AccessKey, SecretKey </sql> <select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap"> select <include refid="Base_Column_List" /> from vts_user where pk_user = #{pkUser,jdbcType=CHAR} </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.String"> delete from vts_user where pk_user = #{pkUser,jdbcType=CHAR} </delete> <insert id="insert" parameterType="com.vipcode.vts.entity.VTSUser"> insert into vts_user (pk_user, dr, use_status, create_date, user_code, user_password, userName, user_sex, pk_status, user_picture, regist_date, login_status, login_platform, login_deivce_code, is_first, openID, weixin_url, weixin_name, bind_tag, bind_date, mac_address, ip_address, AccessKey, SecretKey ) values (#{pkUser,jdbcType=CHAR}, #{dr,jdbcType=INTEGER}, #{useStatus,jdbcType=INTEGER}, #{createDate,jdbcType=CHAR}, #{userCode,jdbcType=VARCHAR}, #{userPassword,jdbcType=VARCHAR}, #{username,jdbcType=VARCHAR}, #{userSex,jdbcType=INTEGER}, #{pkStatus,jdbcType=VARCHAR}, #{userPicture,jdbcType=VARCHAR}, #{registDate,jdbcType=CHAR}, #{loginStatus,jdbcType=INTEGER}, #{loginPlatform,jdbcType=INTEGER}, #{loginDeivceCode,jdbcType=VARCHAR}, #{isFirst,jdbcType=INTEGER}, #{openid,jdbcType=VARCHAR}, #{weixinUrl,jdbcType=VARCHAR}, #{weixinName,jdbcType=VARCHAR}, #{bindTag,jdbcType=VARCHAR}, #{bindDate,jdbcType=CHAR}, #{macAddress,jdbcType=VARCHAR}, #{ipAddress,jdbcType=VARCHAR}, #{accesskey,jdbcType=VARCHAR}, #{secretkey,jdbcType=VARCHAR} ) </insert> <insert id="insertSelective" parameterType="com.vipcode.vts.entity.VTSUser"> insert into vts_user <trim prefix="(" suffix=")" suffixOverrides=","> <if test="pkUser != null"> pk_user, </if> <if test="dr != null"> dr, </if 1fff8 > <if test="useStatus != null"> use_status, </if> <if test="createDate != null"> create_date, </if> <if test="userCode != null"> user_code, </if> <if test="userPassword != null"> user_password, </if> <if test="username != null"> userName, </if> <if test="userSex != null"> user_sex, </if> <if test="pkStatus != null"> pk_status, </if> <if test="userPicture != null"> user_picture, </if> <if test="registDate != null"> regist_date, </if> <if test="loginStatus != null"> login_status, </if> <if test="loginPlatform != null"> login_platform, </if> <if test="loginDeivceCode != null"> login_deivce_code, </if> <if test="isFirst != null"> is_first, </if> <if test="openid != null"> openID, </if> <if test="weixinUrl != null"> weixin_url, </if> <if test="weixinName != null"> weixin_name, </if> <if test="bindTag != null"> bind_tag, </if> <if test="bindDate != null"> bind_date, </if> <if test="macAddress != null"> mac_address, </if> <if test="ipAddress != null"> ip_address, </if> <if test="accesskey != null"> AccessKey, </if> <if test="secretkey != null"> SecretKey, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="pkUser != null"> #{pkUser,jdbcType=CHAR}, </if> <if test="dr != null"> #{dr,jdbcType=INTEGER}, </if> <if test="useStatus != null"> #{useStatus,jdbcType=INTEGER}, </if> <if test="createDate != null"> #{createDate,jdbcType=CHAR}, </if> <if test="userCode != null"> #{userCode,jdbcType=VARCHAR}, </if> <if test="userPassword != null"> #{userPassword,jdbcType=VARCHAR}, </if> <if test="username != null"> #{username,jdbcType=VARCHAR}, </if> <if test="userSex != null"> #{userSex,jdbcType=INTEGER}, </if> <if test="pkStatus != null"> #{pkStatus,jdbcType=VARCHAR}, </if> <if test="userPicture != null"> #{userPicture,jdbcType=VARCHAR}, </if> <if test="registDate != null"> #{registDate,jdbcType=CHAR}, </if> <if test="loginStatus != null"> #{loginStatus,jdbcType=INTEGER}, </if> <if test="loginPlatform != null"> #{loginPlatform,jdbcType=INTEGER}, </if> <if test="loginDeivceCode != null"> #{loginDeivceCode,jdbcType=VARCHAR}, </if> <if test="isFirst != null"> #{isFirst,jdbcType=INTEGER}, </if> <if test="openid != null"> #{openid,jdbcType=VARCHAR}, </if> <if test="weixinUrl != null"> #{weixinUrl,jdbcType=VARCHAR}, </if> <if test="weixinName != null"> #{weixinName,jdbcType=VARCHAR}, </if> <if test="bindTag != null"> #{bindTag,jdbcType=VARCHAR}, </if> <if test="bindDate != null"> #{bindDate,jdbcType=CHAR}, </if> <if test="macAddress != null"> #{macAddress,jdbcType=VARCHAR}, </if> <if test="ipAddress != null"> #{ipAddress,jdbcType=VARCHAR}, </if> <if test="accesskey != null"> #{accesskey,jdbcType=VARCHAR}, </if> <if test="secretkey != null"> #{secretkey,jdbcType=VARCHAR}, </if> </trim> </insert> <update id="updateByPrimaryKeySelective" parameterType="com.vipcode.vts.entity.VTSUser"> update vts_user <set> <if test="dr != null"> dr = #{dr,jdbcType=INTEGER}, </if> <if test="useStatus != null"> use_status = #{useStatus,jdbcType=INTEGER}, </if> <if test="createDate != null"> create_date = #{createDate,jdbcType=CHAR}, </if> <if test="userCode != null"> user_code = #{userCode,jdbcType=VARCHAR}, </if> <if test="userPassword != null"> user_password = #{userPassword,jdbcType=VARCHAR}, </if> <if test="username != null"> userName = #{username,jdbcType=VARCHAR}, </if> <if test="userSex != null"> user_sex = #{userSex,jdbcType=INTEGER}, </if> <if test="pkStatus != null"> pk_status = #{pkStatus,jdbcType=VARCHAR}, </if> <if test="userPicture != null"> user_picture = #{userPicture,jdbcType=VARCHAR}, </if> <if test="registDate != null"> regist_date = #{registDate,jdbcType=CHAR}, </if> <if test="loginStatus != null"> login_status = #{loginStatus,jdbcType=INTEGER}, </if> <if test="loginPlatform != null"> login_platform = #{loginPlatform,jdbcType=INTEGER}, </if> <if test="loginDeivceCode != null"> login_deivce_code = #{loginDeivceCode,jdbcType=VARCHAR}, </if> <if test="isFirst != null"> is_first = #{isFirst,jdbcType=INTEGER}, </if> <if test="openid != null"> openID = #{openid,jdbcType=VARCHAR}, </if> <if test="weixinUrl != null"> weixin_url = #{weixinUrl,jdbcType=VARCHAR}, </if> <if test="weixinName != null"> weixin_name = #{weixinName,jdbcType=VARCHAR}, </if> <if test="bindTag != null"> bind_tag = #{bindTag,jdbcType=VARCHAR}, </if> <if test="bindDate != null"> bind_date = #{bindDate,jdbcType=CHAR}, </if> <if test="macAddress != null"> mac_address = #{macAddress,jdbcType=VARCHAR}, </if> <if test="ipAddress != null"> ip_address = #{ipAddress,jdbcType=VARCHAR}, </if> <if test="accesskey != null"> AccessKey = #{accesskey,jdbcType=VARCHAR}, </if> <if test="secretkey != null"> SecretKey = #{secretkey,jdbcType=VARCHAR}, </if> </set> where pk_user = #{pkUser,jdbcType=CHAR} </update> <update id="updateByPrimaryKey" parameterType="com.vipcode.vts.entity.VTSUser"> update vts_user set dr = #{dr,jdbcType=INTEGER}, use_status = #{useStatus,jdbcType=INTEGER}, create_date = #{createDate,jdbcType=CHAR}, user_code = #{userCode,jdbcType=VARCHAR}, user_password = #{userPassword,jdbcType=VARCHAR}, userName = #{username,jdbcType=VARCHAR}, user_sex = #{userSex,jdbcType=INTEGER}, pk_status = #{pkStatus,jdbcType=VARCHAR}, user_picture = #{userPicture,jdbcType=VARCHAR}, regist_date = #{registDate,jdbcType=CHAR}, login_status = #{loginStatus,jdbcType=INTEGER}, login_platform = #{loginPlatform,jdbcType=INTEGER}, login_deivce_code = #{loginDeivceCode,jdbcType=VARCHAR}, is_first = #{isFirst,jdbcType=INTEGER}, openID = #{openid,jdbcType=VARCHAR}, weixin_url = #{weixinUrl,jdbcType=VARCHAR}, weixin_name = #{weixinName,jdbcType=VARCHAR}, bind_tag = #{bindTag,jdbcType=VARCHAR}, bind_date = #{bindDate,jdbcType=CHAR}, mac_address = #{macAddress,jdbcType=VARCHAR}, ip_address = #{ipAddress,jdbcType=VARCHAR}, AccessKey = #{accesskey,jdbcType=VARCHAR}, SecretKey = #{secretkey,jdbcType=VARCHAR} where pk_user = #{pkUser,jdbcType=CHAR} </update> </mapper>
新建Service层,进行业务处理
[code]/** * <b> </b> * <p> * 功能描述: * </p> * <p/> * @author 朱维 * @date 2018年9月29日 * @time 上午11:18:36 * @Path: com.vipcode.vts.service.impl.UserServiceImpl */ @Service public class UserServiceImpl implements UserService{ /** * 注入数据接口 */ @Autowired private VTSUserMapper vtsUserMapper; /** * 注入数据接口 */ @Autowired private VTSUserAnnotation vtsUserAnnotation; @Override public VTSUser getUser(String pkUser) { // TODO Auto-generated method stub VTSUser vtsUser = vtsUserMapper.selectByPrimaryKey(pkUser); System.out.println(vtsUser); VTSUser vtsUser2 = vtsUserAnnotation.selectByPrimaryKey(pkUser); System.out.println(vtsUser2); return vtsUser2; } @Override public String saveUser(VTSUser vtsUser) { // TODO Auto-generated method stub // vtsUserMapper.insert(vtsUser); vtsUser.setPkUser(Pub_Tools.genUUID()); vtsUserAnnotation.insert(vtsUser); return vtsUser.getPkUser(); } }
编写Controller
[code]@RestController public class UserController { /** * 注入用户Service */ @Autowired private UserService userService; /** * 获取用户 * @param pkUser * @return */ @GetMapping("/user") public VTSUser getUser(@RequestParam("pkUser")String pkUser){ return userService.getUser(pkUser); } /** * 保存用户 * @param vtsUser * @return */ @PostMapping("/save") public String saveUser(VTSUser vtsUser){ return userService.saveUser(vtsUser); } }
测试调用保存的方法,往数据库中插入一条数据,得到返回的主键。
此时去查询Slave的db0,无此条数据
查询Slave的db1,有此条数据,这是Mysql主从复制规则产生的。
使用该主键,调用查询方法,返回数据null。说明查询是从db0中进行查询。由此证明,项目中的读写是分库的。
更改yml配置,设置主库为Master机器的db0,则读写分离配置成功。
阅读更多- 在springboot项目中使用mybatis 集成 Sharding-JDBC
- 基于SpringBoot + Mybatis实现SpringMVC Web项目
- springboot+mybatis+SpringSecurity 实现用户角色数据库管理(一)
- 从零学spring boot--集成mybatis--项目--使用注解方式
- mysql+spring+mybatis实现数据库读写分离[代码配置] .
- 基于SpringBoot + Mybatis实现SpringMVC Web项目【原创】
- J2EE项目使用自定义注解实现基于SpringMVC + Mybatis + Mysql的读写分离
- spring结合mybatis实现数据库读写分离
- Spring Boot 学习二、基于SpringBoot + Mybatis实现SpringMVC Web项目
- 基于SpringBoot + Mybatis实现SpringMVC Web项目【原创】
- 未测试---- mysql+spring+mybatis实现数据库读写分离[代码配置]
- maven项目 spring-boot 整合 mybatis 实现查询功能demo
- mysql+spring+mybatis实现数据库读写分离[代码配置]
- SpringBoot+Maven项目实战(4):集成Mybatis
- Spring boot实现数据库读写分离
- Spring+Mybatis项目中通过继承AbstractRoutingDataSource实现数据库热切换
- Spring Boot 集成Mybatis实现主从(多数据源)分离方案示例
- spring+mybatis+uncode-dal实现数据库读写分离
- sharding-jdbc集成spring+mybatis分表分库
- Spring boot+MyBatis+Sharding jdbc配置