配置文件:bootstrap.yml
# Tomcat
server:
port: 9528
# Spring
spring:
application:
# 应用名称
name: jingce-sharding-gz
profiles:
# 环境配置
active: dev
props:
sql-show: true
配置文件: bootstrap-dev.yml
# Spring
spring:
### 处理连接池冲突 #####
main:
allow-bean-definition-overriding: true
datasource:
driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
url: jdbc:shardingsphere:classpath:sharding-dev.yaml
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 172.16.7.100:8848
# server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 172.16.7.100:8848
# server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-dataids: application-dev.${spring.cloud.nacos.config.file-extension}
logging:
level.root: info
level.com.jingce: debug
pagehelper:
helperDialect: postgresql
配置文件sharding.dev.yaml
dataSources:
abc:
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.jdbc.Driver
jdbcUrl: jdbc:mysql://172.16.7.100:3306/jingce_sharding_abc?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: wervn11l_2Low0OZq
ccb:
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.jdbc.Driver
jdbcUrl: jdbc:mysql://172.16.7.100:3306/jingce_sharding_ccb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: wervn11l_2Low0OZq
rules:
- !SHARDING
tables:
case_follow:
actualDataNodes: abc.case_follow,ccb.case_follow
tableStrategy:
standard:
shardingColumn: create_time
shardingAlgorithmName: auto-custom
databaseStrategy:
standard:
shardingColumn: sys_code
shardingAlgorithmName: auto-custom-db
shardingAlgorithms:
auto-custom:
type: CLASS_BASED
props:
strategy: standard
algorithmClassName: com.jingce.sharding.config.TimeShardingAlgorithm
auto-custom-db:
type: CLASS_BASED
props:
strategy: standard
algorithmClassName: com.jingce.sharding.config.TimeShardingAlgorithmDb
createTable:
jingce_debt_abc:
dbName: abc
jdbcUrl: jdbc:mysql://172.16.7.100:3306/jingce_sharding_abc?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: wervn11l_2Low0OZq
jingce_debt_ccb:
dbName: ccb
jdbcUrl: jdbc:mysql://172.16.7.100:3306/jingce_sharding_ccb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: wervn11l_2Low0OZq
props:
sql-show: true
配置文件项目图:
实体类
package com.jingce.sharding.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDateTime;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
* </p>
*
* @author ywl
* @since 2023-12-05
*/
@Data
public class CaseFollow {
/**
* id
*/
private Long id;
/**
* 部门id
*/
private Long deptId;
/**
* 创建时间(跟进时间)
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@TableField(exist = false)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
@TableField(exist = false)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
}
本地线程工具类:threadLocal,在分库分表实际代码中需要使用
package com.jingce.sharding.config;
import java.util.Map;
public class ThreadLocal {
/**
* 构造函数私有
*/
private ThreadLocal() {
}
private static final java.lang.ThreadLocal<Map<String, String>> threadLocal = new java.lang.ThreadLocal<>();
/**
* 清除用户信息
*/
public static void clear() {
threadLocal.remove();
}
/**
* 存储用户信息
*/
public static void set(Map<String, String> map) {
threadLocal.set(map);
}
/**
* 获取当前用户信息
*/
public static Map<String, String> get() {
return threadLocal.get();
}
}
准备工作做好,下面开始实现具体分库分表操作,以及按月自动建表操作
分库实现类:TimeShardingAlgorithmDb,根据字段配置中的sysCode实现分库
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jingce.sharding.config;
import com.jingce.sharding.utils.SpringUtil;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shardingsphere.sharding.api.sharding.ShardingAutoTableAlgorithm;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;
import org.springframework.core.env.Environment;
import java.sql.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
/**
* <p> @Title TimeShardingAlgorithm
* <p> @Description 分片算法,按月分片
*
* @author ACGkaka
* @date 2022/12/20 11:33
*/
@Slf4j
public class TimeShardingAlgorithmDb implements StandardShardingAlgorithm<String>, ShardingAutoTableAlgorithm {
/** 表分片符号,例:t_user_202201 中,分片符号为 "_" */
private static final String TABLE_SPLIT_SYMBOL = "_";
/** 配置文件路径 */
private static final String CONFIG_FILE = "sharding-tables.yaml";
/**
* 分片时间格式
*/
private static final DateTimeFormatter TABLE_SHARD_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMM");
/**
* 完整时间格式
*/
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss");
@Getter
private Properties props;
@Getter
private int autoTablesAmount;
private static String CREATE_TABLE_DB = "createTable";
private static String DB_NAME = "dbName";
@Override
public void init(final Properties dataSources) {
this.props = dataSources;
}
@SneakyThrows
@Override
public String doSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<String> preciseShardingValue) {
String value = preciseShardingValue.getValue();
log.info(">>>>>>>>>> 【INFO】精确DB分片,节点配置表名:{}", availableTargetNames);
Environment env = SpringUtil.getBean(Environment.class);
String property = env.getProperty("spring.dataSources.abc.username");
System.out.println(property);
// 获取需要创建新表的数据库连接
String createTable = props.getProperty(CREATE_TABLE_DB);
Map<String, Map<String, String>> map = splitWithoutBraces(createTable);
System.out.println(map);
// 获取需要创建表的数据库信息
Map<String, String> dataSourceMap = map.get(value);
ThreadLocal.set(dataSourceMap);
String dbName = dataSourceMap.get(DB_NAME);
for (Map.Entry<String, Map<String, String>> entry : map.entrySet()) {
Map<String, String> mapValue = entry.getValue();
String logicTableName = preciseShardingValue.getLogicTableName();
String jdbcUrl = mapValue.get("jdbcUrl");
String username = mapValue.get("username");
String password = mapValue.get("password");
List<String> allTableNameBySchema = getAllTableNameBySchema(logicTableName, jdbcUrl, username, password);
availableTargetNames.addAll(allTableNameBySchema);
String key = entry.getKey();
if (!availableTargetNames.contains(key)){
availableTargetNames.add(key);
}
}
return dbName;
}
public static Map<String, Map<String, String>> splitWithoutBraces(String input) {
// 去掉收尾大括号
input = input.replaceFirst("\\{", "").replaceFirst("\\}$", "");
List<String> list = new ArrayList<>();
int braceLevel = 0;
int start = 0;
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
if (ch == '{') {
braceLevel++;
} else if (ch == '}') {
braceLevel--;
} else if (ch == ',' && braceLevel == 0) {
list.add(input.substring(start, i).trim());
start = i + 1;
}
}
list.add(input.substring(start).trim());
System.out.println(list);
Map<String, Map<String, String>> map = new HashMap<>();
for (String str : list) {
String[] sp = str.replaceFirst("=", "#@&").split("#@&");
String key = sp[0];
String value = sp[1];
HashMap<String, String> valueMap = new HashMap<>();
List<String> valueList = Arrays.asList(value.replaceAll("\\{", "").replaceAll("}", "").split(","));
for (String s : valueList) {
String[] split = s.replaceFirst("=", "#@&").split("#@&");
valueMap.put(split[0].trim(),split[1].trim());
}
map.put(key.trim(),valueMap);
}
return map;
}
@Override
public Collection<String> doSharding(final Collection<String> availableTargetNames, final RangeShardingValue<String> rangeShardingValue) {
log.info(">>>>>>>>>> 【INFO】范围DB分片,节点配置表名:{}", availableTargetNames);
return null;
}
@Override
public String getType() {
return "auto-custom-db";
}
// @Override
// public Collection<String> doSharding(Collection<String> availableTargetNames, HintShardingValue<String> shardingValue) {
// List<String> tables = new ArrayList<>();
// tables.add("ds1");
// return tables;
// }
/**
* 获取所有表名
* @return 表名集合
* @param logicTableName 逻辑表
*/
public List<String> getAllTableNameBySchema(String logicTableName,String jdbcUrl,String username,String password) {
List<String> tableNames = new ArrayList<>();
if (StringUtils.isEmpty(jdbcUrl) || StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
log.error(">>>>>>>>>> 【ERROR】数据库连接配置有误,请稍后重试,URL:{}, username:{}, password:{}", jdbcUrl, username, password);
throw new IllegalArgumentException("数据库连接配置有误,请稍后重试");
}
try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password);
Statement st = conn.createStatement()) {
try (ResultSet rs = st.executeQuery("show TABLES like '" + logicTableName + TABLE_SPLIT_SYMBOL + "%'")) {
while (rs.next()) {
String tableName = rs.getString(1);
// 匹配分表格式 例:^(t\_contract_\d{6})$
if (tableName != null && tableName.matches(String.format("^(%s\\d{6})$", logicTableName + TABLE_SPLIT_SYMBOL))) {
tableNames.add(rs.getString(1));
}
}
}
} catch (SQLException e) {
log.error(">>>>>>>>>> 【ERROR】数据库连接失败,请稍后重试,原因:{}", e.getMessage(), e);
throw new IllegalArgumentException("数据库连接失败,请稍后重试");
}
return tableNames;
}
}
分表实现类:可以根据实体类中createTime区分当前数据是几月份并自动按月份建表例如case_follow_202404
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jingce.sharding.config;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Range;
import com.jingce.common.core.utils.DateUtils;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shardingsphere.sharding.api.sharding.ShardingAutoTableAlgorithm;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;
import java.sql.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.*;
/**
* <p> @Title TimeShardingAlgorithm
* <p> @Description 分片算法,按月分片
*
* @author ACGkaka
* @date 2022/12/20 11:33
*/
@Slf4j
public class TimeShardingAlgorithm implements StandardShardingAlgorithm<String>, ShardingAutoTableAlgorithm {
/** 表分片符号,例:t_user_202201 中,分片符号为 "_" */
private static final String TABLE_SPLIT_SYMBOL = "_";
/** 配置文件路径 */
private static final String CONFIG_FILE = "sharding-tables.yaml";
/**
* 分片时间格式
*/
private static final DateTimeFormatter TABLE_SHARD_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMM");
/**
* 完整时间格式
*/
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss");
@Getter
private Properties props;
@Getter
private int autoTablesAmount;
@Override
public void init(final Properties props) {
this.props = props;
}
@SneakyThrows
@Override
public String doSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<String> preciseShardingValue) {
String logicTableName = preciseShardingValue.getLogicTableName();
log.info(">>>>>>>>>> 【INFO】精确分片,节点配置表名:{}", availableTargetNames);
// availableTargetNames.add("case_follow");
String monthStr = "";
Object value = preciseShardingValue.getValue();
if (value instanceof Date){
System.out.println(111);
DateFormat dateFormat = new SimpleDateFormat("yyyyMM");
monthStr = dateFormat.format(value);
}else if (value instanceof LocalDateTime){
System.out.println(222);
LocalDateTime parse = LocalDateTime.parse(value.toString());
monthStr = parse.format(TABLE_SHARD_TIME_FORMATTER);
}
System.out.println(monthStr);
String resultTableName = logicTableName + "_" + monthStr;
System.out.println(resultTableName);
String jdbcUrl = "";
String username = "";
String password = "";
Map<String, String> map = ThreadLocal.get();
if (ObjectUtil.isNotNull(map)){
jdbcUrl = map.get("jdbcUrl");
username = map.get("username");
password = map.get("password");
// 用完之后清空ThreadLocal
ThreadLocal.clear();
System.out.println(jdbcUrl);
System.out.println(username);
System.out.println(password);
// 查询催记所有分表节点
List<String> allTableNameBySchema = getAllTableNameBySchema(logicTableName,jdbcUrl,username,password);
System.out.println(allTableNameBySchema);
for (String table : allTableNameBySchema) {
if (!availableTargetNames.contains(table)){
availableTargetNames.add(table);
}
}
// availableTargetNames.clear();
// availableTargetNames.addAll(allTableNameBySchema);
return getShardingTableAndCreate(logicTableName, resultTableName, availableTargetNames, jdbcUrl, username, password);
}
return resultTableName;
}
@Override
public Collection<String> doSharding(final Collection<String> availableTargetNames, final RangeShardingValue<String> rangeShardingValue) {
log.info(">>>>>>>>>> 【INFO】范围分片,节点配置表名:{}", availableTargetNames);
String logicTableName = rangeShardingValue.getLogicTableName();
List<String> list = new ArrayList<>();
Range<String> valueRange = rangeShardingValue.getValueRange();
Object startValue = valueRange.lowerEndpoint();
Object endValue = valueRange.upperEndpoint();
String startMonth = "";
if (startValue instanceof Date){
DateFormat dateFormat = new SimpleDateFormat("yyyyMM");
startMonth = dateFormat.format(startValue);
}else if (startValue instanceof LocalDateTime){
LocalDateTime parse = LocalDateTime.parse(startValue.toString());
startMonth = parse.format(TABLE_SHARD_TIME_FORMATTER);
}
String endMonth = "";
if (endValue instanceof Date){
DateFormat dateFormat = new SimpleDateFormat("yyyyMM");
endMonth = dateFormat.format(endValue);
}else if (endValue instanceof LocalDateTime){
LocalDateTime parse = LocalDateTime.parse(endValue.toString());
endMonth = parse.format(TABLE_SHARD_TIME_FORMATTER);
}
// list.add("case_follow");
List<String> yearMonthsBetween = DateUtils.getYearMonthsBetween(startMonth, endMonth);
for (String yearMonth : yearMonthsBetween) {
String resultTableName = logicTableName + "_" + yearMonth;
if (availableTargetNames.contains(resultTableName)){
list.add(resultTableName);
}
}
return list;
}
@Override
public String getType() {
return "AUTO_CUSTOM";
}
/**
* 获取所有表名
* @return 表名集合
* @param logicTableName 逻辑表
*/
public List<String> getAllTableNameBySchema(String logicTableName,String jdbcUrl,String username,String password) {
List<String> tableNames = new ArrayList<>();
if (StringUtils.isEmpty(jdbcUrl) || StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
log.error(">>>>>>>>>> 【ERROR】数据库连接配置有误,请稍后重试,URL:{}, username:{}, password:{}", jdbcUrl, username, password);
throw new IllegalArgumentException("数据库连接配置有误,请稍后重试");
}
try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password);
Statement st = conn.createStatement()) {
try (ResultSet rs = st.executeQuery("show TABLES like '" + logicTableName + TABLE_SPLIT_SYMBOL + "%'")) {
while (rs.next()) {
String tableName = rs.getString(1);
// 匹配分表格式 例:^(t\_contract_\d{6})$
if (tableName != null && tableName.matches(String.format("^(%s\\d{6})$", logicTableName + TABLE_SPLIT_SYMBOL))) {
tableNames.add(rs.getString(1));
}
}
}
} catch (SQLException e) {
log.error(">>>>>>>>>> 【ERROR】数据库连接失败,请稍后重试,原因:{}", e.getMessage(), e);
throw new IllegalArgumentException("数据库连接失败,请稍后重试");
}
return tableNames;
}
/**
* 检查分表获取的表名是否存在,不存在则自动建表
* @param logicTableName 逻辑表
* @param resultTableName 真实表名,例:t_user_202201
* @return 确认存在于数据库中的真实表名
*/
public String getShardingTableAndCreate(String logicTableName, String resultTableName, Collection<String> availableTargetNames,String jdbcUrl,String username,String password) {
// 缓存中有此表则返回,没有则判断创建
if (availableTargetNames.contains(resultTableName)) {
return resultTableName;
} else {
// 检查分表获取的表名不存在,需要自动建表
boolean isSuccess = createShardingTable(logicTableName, resultTableName,jdbcUrl,username,password);
if (isSuccess) {
// 如果建表成功,需要更新缓存
availableTargetNames.add(resultTableName);
autoTablesAmount++;
return resultTableName;
} else {
// 如果建表失败,返回逻辑空表
return logicTableName;
}
}
}
/**
* 创建分表2
* @param logicTableName 逻辑表
* @param resultTableName 真实表名,例:t_user_202201
* @return 创建结果(true创建成功,false未创建)
*/
public boolean createShardingTable(String logicTableName, String resultTableName,String jdbcUrl,String username,String password) {
// 根据日期判断,当前月份之后分表不提前创建
String month = resultTableName.replace(logicTableName + TABLE_SPLIT_SYMBOL,"");
YearMonth shardingMonth = YearMonth.parse(month, DateTimeFormatter.ofPattern("yyyyMM"));
if (shardingMonth.isAfter(YearMonth.now())) {
return false;
}
synchronized (logicTableName.intern()) {
// 缓存中无此表,则建表并添加缓存
executeSql(Collections.singletonList("CREATE TABLE IF NOT EXISTS `" + resultTableName + "` LIKE `" + logicTableName + "`;"),jdbcUrl,username,password);
}
return true;
}
/**
* 执行SQL
* @param sqlList SQL集合
*/
private void executeSql(List<String> sqlList,String jdbcUrl,String username,String password) {
if (StringUtils.isEmpty(jdbcUrl) || StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
log.error(">>>>>>>>>> 【ERROR】数据库连接配置有误,请稍后重试,URL:{}, username:{}, password:{}", jdbcUrl, username, password);
throw new IllegalArgumentException("数据库连接配置有误,请稍后重试");
}
try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) {
try (Statement st = conn.createStatement()) {
conn.setAutoCommit(false);
for (String sql : sqlList) {
st.execute(sql);
}
} catch (Exception e) {
conn.rollback();
log.error(">>>>>>>>>> 【ERROR】数据表创建执行失败,请稍后重试,原因:{}", e.getMessage(), e);
throw new IllegalArgumentException("数据表创建执行失败,请稍后重试");
}
} catch (SQLException e) {
log.error(">>>>>>>>>> 【ERROR】数据库连接失败,请稍后重试,原因:{}", e.getMessage(), e);
throw new IllegalArgumentException("数据库连接失败,请稍后重试");
}
}
}
重要:项目启动后,需要主动执行一次查询动作,目的是为了将分库分表的配置加载到缓存中,
如果内存的缓存中没有分库分表的配置,查询会没有数据
详细可以参考:https://blog.csdn.net/qq_33204709/article/details/132590731?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-132590731-blog-131208779.235%5Ev38%5Epc_relevant_anti_t3_base&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-132590731-blog-131208779.235%5Ev38%5Epc_relevant_anti_t3_base&utm_relevant_index=1
这个地址有具体的自动按月分表方案,但是我自己的代码中有根据项目实际的分库并分表存储数据方案,可以多多参考达到自己的目的
package com.jingce.sharding.config;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jingce.sharding.domain.CaseFollow;
import com.jingce.sharding.service.ICaseFollowService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.List;
/**
* <p> @Title ShardingTablesLoadRunner
* <p> @Description 项目启动后,读取已有分表,进行缓存
*
* @author ACGkaka
* @date 2022/12/20 15:41
*/
@Slf4j
//@Order(value = 100) // 数字越小,越先执行
@Component
public class ShardingTablesLoadRunner implements CommandLineRunner {
// @Autowired
// private UserService userService;
@Autowired
private ICaseFollowService caseFollowService;
@Override
public void run(String... args) {
// 读取已有分表,进行缓存
// LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
// queryWrapper.eq(User::getCreateTime, LocalDateTime.now()).last("limit 1");
// List<User> list = userService.list(queryWrapper);
// System.out.println(list);
LambdaQueryWrapper<CaseFollow> queryWrapper = new LambdaQueryWrapper<>();
// queryWrapper.eq(CaseFollow::getCreateTime, LocalDateTime.now()).last("limit 1");
queryWrapper.eq(CaseFollow::getSysCode,"jingce_debt_abc").eq(CaseFollow::getCreateTime, LocalDateTime.now()).last("limit 1");
List<CaseFollow> list = caseFollowService.list(queryWrapper);
System.out.println(list);
log.info(">>>>>>>>>> 【ShardingTablesLoadRunner】缓存已有分表成功 <<<<<<<<<<");
}
}
pom文件:改配置中可能存在项目中自己的一些配置,不需要可以删除点
<dependencies>
<!-- SpringCloud Ailibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Ailibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Ailibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<!-- Mysql Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- RuoYi Common Datascope -->
<dependency>
<groupId>com.jingce</groupId>
<artifactId>jingce-common-datascope</artifactId>
</dependency>
<!-- RuoYi Common Log -->
<dependency>
<groupId>com.jingce</groupId>
<artifactId>jingce-common-log</artifactId>
</dependency>
<!-- RuoYi Common Swagger -->
<dependency>
<groupId>com.jingce</groupId>
<artifactId>jingce-common-swagger</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.8.3</version>
<scope>compile</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-httpclient/commons-httpclient -->
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<!-- Sharding-JDBC -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core</artifactId>
<version>5.3.0</version>
</dependency>
<!-- Mybatis的分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
项目架构图: