springboot 集成 shardingSphere 加mybatisplus 自带增加 分页查询 和源代码包 分库分表 单库 分表 使用雪花算法id
目录
介绍
代码下载
效果
数据库
代码结构
上代码
pom.xml
yml配置
建表语句
mapper.xml
mybatisplus 配置.java
logback
application.java
BaseEntity
TUser
TUserMapper
TUserService
TUserServiceImpl
TUserController
测试
介绍
这套springboot + sharding sphere + mybatis plus 代码中有很多注释的,是可有可无类型,id放到了父类中,防止save 的时候,id变成0问题 实现id自动生成,全套一个shardingspere
代码下载
https://download.csdn.net/download/weixin_42749765/87759588
效果
数据库
代码结构
上代码
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<start-class>com.superbase.fintech.Application</start-class>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.15</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.1</version>
</dependency>
</dependencies>
yml配置
server:
port: 8080
spring:
main:
allow-bean-definition-overriding: true
shardingsphere:
props:
sql:
show: true # 开启sql日志输出
datasource:
names: t0,t1
t0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test_0?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
username: root
password: admin
t1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test_1?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
username: root
password: admin
sharding:
tables:
t_user:
actual-data-nodes: t0.t_user_$->{0..1}
table-strategy:
inline:
sharding-column: id
algorithm-expression: t_user_$->{id % 2}
key-generator:
column: id
type: SNOWFLAKE
binding-tables: t_user
pagehelper:
# 指定使用的数据库数据库
helperDialect: mysql
# reasonable:分页合理化参数,默认值为false。当该参数设置为 true 时,pageNum<=0 时会查询第一页,pageNum>pages(超过总数时),会查询最后一页。默认false 时,直接根据参数进行查询。
reasonable: true
supportMethodsArguments: true
params: count=countSql
mybatis-plus:
# 扫描 mapper.xml
mapper-locations: classpath*:mapper/**/**.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: com.superbase.fintech
global-config:
db-config:
#主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
id-type: auto
#字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
field-strategy: 0
#驼峰下划线转换
column-underline: false
#逻辑删除配置 使用mybatis plus内置方法默认过滤配置的逻辑删除字段,其他sql需手动过滤sql语句
logic-delete-field: deleteFlag
logic-delete-value: 1
logic-not-delete-value: 0
db-type: mysql
refresh: false
configuration:
jdbc-type-for-null: 'null'
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true
cache-enabled: false # 二级缓存是否开启
lazyLoadingEnabled: true #延时加载的开关
aggressiveLazyLoading: false #开启的话,延时加载一个属性时会加载该对象全部属性,否则按需加载属性
multipleResultSetsEnabled: true
建表语句
CREATE TABLE `t_user_0` (
`id` bigint NOT NULL,
`name` varchar(255) DEFAULT NULL,
`age` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `t_user_1` (
`id` bigint NOT NULL,
`name` varchar(255) DEFAULT NULL,
`age` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
mapper.xml
<?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.superbase.fintech.biz.mapper.TUserMapper">
</mapper>
mybatisplus 配置.java
package com.superbase.fintech.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
logback
<?xml version="1.0" encoding="UTF-8"?>
<!-- 分级别异步文件日志输出配置 -->
<!-- 级别从高到低 OFF 、 FATAL 、 ERROR 、 WARN 、 INFO 、 DEBUG 、 TRACE 、 ALL -->
<!-- 日志输出规则 根据当前ROOT 级别,日志输出时,级别高于root默认的级别时 会输出 -->
<!-- 以下 每个配置的 filter 是过滤掉输出文件里面,会出现高级别文件,依然出现低级别的日志信息,通过filter 过滤只记录本级别的日志 -->
<!-- scan 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。 -->
<!-- scanPeriod 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- logback项目名称 -->
<property name="appName" value="super-base"/>
<!-- 日志级别 DEBUG INFO WARN ERROR -->
<property name="logLevel" value="INFO"/>
<!-- 日志路径-->
<property name="logPath" value="/export/log"/>
<!-- 最大保存时间 30天-->
<property name="maxHistory" value="3"/>
<!-- 异步缓冲队列的深度,该值会影响性能.默认值为256 -->
<property name="queueSize" value="256"/>
<!-- lOGGER PATTERN 根据个人喜好选择匹配 -->
<property name="logPattern" value="%d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0} %X{traceId} - %m%n"/>
<!-- 动态日志级别 -->
<jmxConfigurator/>
<!-- 控制台的标准输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<charset>UTF-8</charset>
<pattern>${logPattern}</pattern>
</encoder>
</appender>
<appender name="consoleDetail" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/${appName}/${appName}_detail.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logPath}/${appName}/detail/${appName}_detail.log.%d{yyyy-MM-dd}.zip</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${logPattern}</pattern>
</encoder>
</appender>
<!-- DUBUG 日志记录 -->
<appender name="FILE_DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<file>${logPath}/${appName}/${appName}_debug.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logPath}/${appName}/debug/${appName}_debug.log.%d{yyyy-MM-dd}.zip
</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${logPattern}</pattern>
</encoder>
</appender>
<!-- INFO 级别的日志记录 -->
<appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<file>${logPath}/${appName}/${appName}_info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logPath}/${appName}/info/${appName}_info.log.%d{yyyy-MM-dd}.zip
</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${logPattern}</pattern>
</encoder>
</appender>
<!-- WARN 级别的日志记录 -->
<appender name="FILE_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<file>${logPath}/${appName}/${appName}_warn.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logPath}/${appName}/warn/${appName}_warn.log.%d{yyyy-MM-dd}.zip
</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${logPattern}</pattern>
</encoder>
</appender>
<!-- Error 级别的日志记录 -->
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<file>${logPath}/${appName}/${appName}_error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logPath}/${appName}/error/${appName}_error.log.%d{yyyy-MM-dd}.zip
</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${logPattern}</pattern>
</encoder>
</appender>
<appender name="ASYNC_consoleDetail" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>${queueSize}</queueSize>
<appender-ref ref="consoleDetail"/>
</appender>
<!-- ASYNC_LOG_DEBUG -->
<appender name="ASYNC_LOG_DEBUG" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>${queueSize}</queueSize>
<appender-ref ref="FILE_DEBUG"/>
</appender>
<!-- ASYNC_LOG_INFO -->
<appender name="ASYNC_LOG_INFO" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>${queueSize}</queueSize>
<appender-ref ref="FILE_INFO"/>
</appender>
<!-- ASYNC_LOG_WARN -->
<appender name="ASYNC_LOG_WARN" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>${queueSize}</queueSize>
<appender-ref ref="FILE_WARN"/>
</appender>
<!--ASYNC_LOG_ERROR -->
<appender name="ASYNC_LOG_ERROR" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>${queueSize}</queueSize>
<appender-ref ref="FILE_ERROR"/>
</appender>
<logger name="org.springframework.web.servlet.DispatcherServlet" level="OFF"/>
<logger name="org.springframework.web.context.support.XmlWebApplicationContext" level="OFF"/>
<logger name="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" level="OFF"/>
<!-- 日志的记录级别 -->
<!-- 在定义后引用APPENDER -->
<root level="${logLevel}">
<!-- 控制台 -->
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNC_consoleDetail"/>
<!-- 具体的日志级别和文件的配置 -->
<appender-ref ref="ASYNC_LOG_DEBUG"/>
<appender-ref ref="ASYNC_LOG_INFO"/>
<appender-ref ref="ASYNC_LOG_WARN"/>
<appender-ref ref="ASYNC_LOG_ERROR"/>
</root>
</configuration>
appplication.properties 里边空的就不写了
application.java
package com.superbase.fintech;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
/**
* Application
*
* @author jianghaoyu
*/
//@SpringBootApplication
@Slf4j
@MapperScan("com.superbase.fintech.biz.mapper")
@SpringBootApplication(exclude={DruidDataSourceAutoConfigure.class})
public class Application {
public static void main(String[] args) {
log.info(" 服务端启动开始");
SpringApplication.run(Application.class, args);
log.info("服务端启动成功");
}
}
BaseEntity
package com.superbase.fintech.biz.entity;
import lombok.Data;
@Data
public class BaseEntity {
private long id;
}
TUser
package com.superbase.fintech.biz.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @author jianghaoyu
* @since 2023-04-28
*/
@Data
//@EqualsAndHashCode(callSuper = true)
//@Accessors(chain = true)
//@TableName("t_user")
//public class TUser extends Model<TUser> {
public class TUser extends BaseEntity{
/**
* 主键Id 必须注释掉,才可自动生成
*/
// private long id;
/**
* 名称
*/
private String name;
/**
* 年龄
*/
private int age;
}
TUserMapper
package com.superbase.fintech.biz.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.superbase.fintech.biz.entity.TUser;
/**
* <p>
* 系统用户表 Mapper 接口
* </p>
*
* @author jianghaoyu
* @since 2023-04-28
*/
public interface TUserMapper extends BaseMapper<TUser> {
}
TUserService
package com.superbase.fintech.biz.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.superbase.fintech.biz.entity.TUser;
import java.util.List;
public interface TUserService extends IService<TUser> {
/**
* 保存用户信息
*
* @param entity
* @return
*/
@Override
boolean save(TUser entity);
/**
* 查询全部用户信息
*
* @return
*/
List<TUser> getUserList();
}
TUserServiceImpl
package com.superbase.fintech.biz.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.superbase.fintech.biz.entity.TUser;
import com.superbase.fintech.biz.mapper.TUserMapper;
import com.superbase.fintech.biz.service.TUserService;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TUserServiceImpl extends ServiceImpl<TUserMapper, TUser> implements TUserService {
@Override
public boolean save(TUser entity) {
return super.save(entity);
}
@Override
public List<TUser> getUserList() {
return baseMapper.selectList(Wrappers.lambdaQuery());
}
}
TUserController
package com.superbase.fintech.biz.ctr;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.superbase.fintech.biz.entity.TUser;
import com.superbase.fintech.biz.mapper.TUserMapper;
import com.superbase.fintech.biz.service.TUserService;
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 java.util.List;
/**
* TUserController
* @author jianghaoyu
*
*/
@RestController
public class TUserController {
@Autowired
private TUserService userService;
@Autowired
private TUserMapper tUserMapper;
@GetMapping("/page")
public IPage<TUser> page() {
QueryWrapper<TUser> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("age");
Page<TUser> page = new Page<>(2, 5);
IPage<TUser> pageList = userService.page(page, queryWrapper);
return pageList;
}
@GetMapping("/save")
public Boolean insert(TUser user) {
TUser t = new TUser();
t.setName("cccccccccccccccc");
return userService.save(t);
}
@RequestMapping("/dao/save")
public String save() {
TUser t = new TUser();
t.setName("SS");
tUserMapper.insert(t);
return "true";
}
}
测试
http://localhost:8080/save
http://localhost:8080/page
ok
持续更新