- 921. Minimum Add to Make Parentheses Valid 使括号有效的最少添加
- 915. Partition Array into Disjoint Intervals 分割数组
- 932. Beautiful Array 漂亮数组
- 940. Distinct Subsequences II 不同的子序列 II
框架搭建:SpringBoot + HikariCP/Druid + Mybatis + Mysql+sharding-jdbc
1、POM依赖:
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
2、配置允许数据源覆盖
properties
文件加入以下配置
# 允许数据源覆盖
spring.main.allow-bean-definition-overriding=true
3、数据源配置
数据源类型通常选择DruidDataSource
或者HikariDataSource
两者在配置上有所不同。
<!-- 不能使用druid-spring-boot-starter,会导致:Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>version</version>
</dependency>
com.alibaba.druid.pool.DruidDataSource
DruidDataSource需要引入druid的Jar包,使用:url
spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.url=
com.zaxxer.hikari.HikariDataSource
HikariDataSource要使用:jdbc-url
spring.shardingsphere.datasource.m1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.m1.jdbc-url=
将用户(user)表,进行水平分表,分为:user_202201,user_202202.... user_202212
//创建数据表
CREATE TABLE user_1/user_2/..../user_6 (
id BIGINT(20) NOT NULL COMMENT 'Id',
name VARCHAR(20) NOT NULL COMMENT '名称',
phone VARCHAR(20) NOT NULL COMMENT '电话',
email VARCHAR(20) NOT NULL COMMENT '邮箱',
create_time TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '操作时间',
PRIMARY KEY (id)
)
server.port=9090
server.servlet.context-path=/demo
spring.application.name=sharding-jdbc-simple-demo
# 允许数据源覆盖
spring.main.allow-bean-definition-overriding=true
# MyBatis配置
# 搜索指定包别名
mybatis.typeAliasesPackage=com.lhz.sharding.model.entity
# 配置mapper的扫描,找到所有的mapper.xml映射文件
mybatis.mapperLocations=classpath*:mybatis/**/*.xml
#数据库类型
mybatis.configuration.database-id=mysql
#自动驼峰转换
mybatis.configuration.map-underscore-to-camel-case=true
#pagehelper 分页插件
pagehelper.helper-dialect=mysql
pagehelper.reasonable=false
pagehelper.support-methods-arguments=true
pagehelper.params=count=countSql
# 数据源名称,多数据源逗号隔开
spring.shardingsphere.datasource.names=m1
spring.shardingsphere.datasource.m1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.jdbc-url=jdbc:mysql://127.0.0.1:3307/shardingjdbc?useUnicode=true&useSSL=false&zeroDateTimeBehavior=convertToNull&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=lhzlx
# 水平分表:user_202201、user_202202、user_202203..,多个表进行分表时,依次在tables标签后写逻辑
# user_202201、user_202202、user_202203... 为数据库中的事实表
# user为xml编码中操作的逻辑表,sharding-jdbc会自动根据策略操作事实表
# 配置节点分布情况,表示可以容纳user_202201到user_203212 张表,根据时间情况定
spring.shardingsphere.sharding.tables.user.actual-data-nodes=m1.user_$->{2022..2032}$->{(1..12).collect{t ->t.toString().padLeft(2,'0')}}
# 指定user表的主键生成策略为SNOWFLAKE
spring.shardingsphere.sharding.tables.user.key-generator.column=id
spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE
# 指定user表的分片策略,分片策略包括分片键和分片算法
# 配置表的分片策略
spring.shardingsphere.sharding.tables.user.table-strategy.standard.sharding-column=create_time
# 精确分片算法类名称,用于 = 和 IN。该类需实现 PreciseShardingAlgorithm 接口并提供无参数的构造器
spring.shardingsphere.sharding.tables.user.table-strategy.standard.precise-algorithm-class-name=\
com.lhz.sharding.algorithm.DatePreciseShardingAlgorithm
# 范围分片算法类名称,用于 范围查询 可选。该类需实现 RangeShardingAlgorithm 接口并提供无参数的构造器
spring.shardingsphere.sharding.tables.user.table-strategy.standard.range-algorithm-class-name=\
com.lhz.sharding.algorithm.DateRangeShardingAlgorithm
# 打开sql输出日志
spring.shardingsphere.props.sql.show=true
DatePreciseShardingAlgorithm:
public class DatePreciseShardingAlgorithm implements PreciseShardingAlgorithm<Date> {
/**
* 精确匹配查询
*
* @param tbNames 数据库中所有的事实表
* @param shardingValue 分片相关信息
* @return 返回匹配的数据源
*/
@Override
public String doSharding(Collection<String> tbNames, PreciseShardingValue<Date> shardingValue) {
String logicTableName = shardingValue.getLogicTableName();
// 匹配满足当前分片规则的表名称
Date date = shardingValue.getValue();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH) + 1;
String monthStr = month >= 10 ? month + "" : "0" + month;
String value = year + monthStr;
return logicTableName + "_" + value;
}
}
DateRangeShardingAlgorithm:
public class DateRangeShardingAlgorithm implements RangeShardingAlgorithm<Date> {
@Override
public Collection<String> doSharding(Collection<String> tbNames, RangeShardingValue<Date> rangeShardingValue) {
// 获取逻辑表名称
String logicTableName = rangeShardingValue.getLogicTableName();
// between and 的起始值,需要处理只有最大值或者只有最小值的情况
boolean hasLowerBound = rangeShardingValue.getValueRange().hasLowerBound();
boolean hasUpperBound = rangeShardingValue.getValueRange().hasUpperBound();
long max = 0;
long min = 0;
// 只有最小值,比如:id > x
if (hasLowerBound && !hasUpperBound) {
Date lower = rangeShardingValue.getValueRange().lowerEndpoint();
// 直接大于最小值的表
String suffix = getSuffix(lower);
min = Long.parseLong(suffix);
// 获取最大的日期表
ArrayList<String> arrayList = new ArrayList<>(tbNames);
String maxSuffix = arrayList.get(tbNames.size() - 1).split("_")[1];
max = Long.parseLong(maxSuffix);
} else if (!hasLowerBound && hasUpperBound) {
// 只有最大值,比如:id < x
Date upper = rangeShardingValue.getValueRange().upperEndpoint();
String suffix = getSuffix(upper);
max = Long.parseLong(suffix);
// 获取最小的日期表
ArrayList<String> arrayList = new ArrayList<>(tbNames);
String maxSuffix = arrayList.get(0).split("_")[1];
min = Long.parseLong(maxSuffix);
} else {
// 区间值情况
Date lower = rangeShardingValue.getValueRange().lowerEndpoint();
Date upper = rangeShardingValue.getValueRange().upperEndpoint();
String lowerSuffix = getSuffix(lower);
String upperSuffix = getSuffix(upper);
min = Long.parseLong(lowerSuffix);
max = Long.parseLong(upperSuffix);
}
// 拼接事实表名称
return matchMinAndMax(min, max, logicTableName);
}
private List<String> matchMinAndMax(long lower, long upper, String logicTableName) {
List<String> tableNameList = new ArrayList<>();
for (long index = lower; index <= upper; index++) {
String tableName = logicTableName + "_" + index;
tableNameList.add(tableName);
}
return tableNameList;
}
/**
* 获取逻辑表后缀
*
* @param date
* @return
*/
private String getSuffix(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH) + 1;
String monthStr = month >= 10 ? month + "" : "0" + month;
return year + monthStr;
}
}
User :
@Data
public class User implements Serializable {
private Long id;
private String name;
private String phone;
private String email;
private Date createTime;
}
DateMapper:
@Mapper
public interface DateMapper {
/**
* 新增数据
*
* @param minTime
* @param minTime
* @return
*/
List<User> listByRange(@Param("minTime") Date minTime, @Param("maxTime") Date maxTime);
/**
* @param user
* @return
*/
int insert(User user);
/**
* @param list
* @return
*/
int insertBatch(List<User> list);
}
DateMapper.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.lhz.sharding.mapper.DateMapper">
<select id="listByRange"
resultType="com.lhz.sharding.model.entity.User">
select a.*
from user a
where a.create_time >={minTime}
and a.create_time <={maxTime}
</select>
<insert id="insert" parameterType="com.lhz.sharding.model.entity.User">
insert into user(id, name, phone, email, create_time)
values (#{id},{name},{phone},{email},{createTime})
</insert>
<insert id="insertBatch" parameterType="com.lhz.sharding.model.entity.User">
insert into user(id, name, phone, email,create_time)
values
<foreach collection="list" item="item" separator=",">
(#{item.id},{item.name},{item.phone},{item.email},{item.createTime})
</foreach>
</insert>
</mapper>
DateService:
@Service
public class DateService {
@Resource
private DateMapper dateMapper;
/**
* 范围查询
*
* @param minTime
* @param maxTime
* @return
*/
public List<User> listByRange(Date minTime, Date maxTime) {
return dateMapper.listByRange(minTime, maxTime);
}
/**
* 新增数据
*
* @return
*/
@ApiOperation(value = "新增数据", notes = "新增数据")
@ApiOperationSupport(order = 25)
@GetMapping("/insert")
public int insert() {
// 模拟数据
List<User> list = new ArrayList<>();
for (long a = 1; a <= 10; a++) {
User user = new User();
long id = new Random().nextInt(99999999);
user.setId(id);
user.setName("测试名称-" + a);
user.setPhone("176-" + a);
user.setEmail("123@com-" + a);
user.setEmail("123@com-" + a);
// 时间戳,从2022-01-01随机到2022-04-30
long time = (16409664 + new Random().nextInt(102816)) * 100000L;
user.setCreateTime(new Date(time));
list.add(user);
}
// 批量新增
dateMapper.insertBatch(list);
// 单个新增
User user = new User();
long id = new Random().nextInt(99999999);
user.setId(id);
user.setName("测试名称-" + 999);
user.setPhone("176-" + 999);
user.setEmail("123@com-" + 999);
// 时间戳,从2022-01-01随机到2022-04-30
long time = (16409664 + new Random().nextInt(102816)) * 100000L;
user.setCreateTime(new Date(time));
return dateMapper.insert(user);
}
}
DateController:
@RestController
@RequestMapping("date")
public class DateController {
@Resource
private DateService dateService;
/**
* 范围查询
*
* @return
*/
@GetMapping("/listByRange")
public List<User> listByRange() {
// 模拟时间区间时间戳
long minTime = 1644331100000L;
long maxTime = 1651248000000L;
return dateService.listByRange(new Date(minTime), new Date(maxTime));
}
/**
* 新增数据
*
* @return
*/
@GetMapping("/insert")
public int insert() {
return dateService.insert();
}
}
1、查询:
查询的时间范围从2022-02-08 22:38:20
到2022-04-30 00:00:00
所以设置的表分别为:user_202202
,user_202203
,user_202204
共三张
2、新增:
新增时的日期为2022-01-08 03:06:40
,所以操作表user_202201
我正在努力做到这一点 在我的操作中从数据库获取对象列表(确定) 在 JSP 上打印(确定) 此列表作为 JSP 中的可编辑表出现。我想修改然后将其提交回同一操作以将其保存在我的数据库中(失败。当我使用
我有以下形式的 Linq to Entities 查询: var x = from a in SomeData where ... some conditions ... select
我有以下查询。 var query = Repository.Query() .Where(p => !p.IsDeleted && p.Article.ArticleSections.Cou
我正在编写一个应用程序包,其中包含一个主类,其中主方法与GUI类分开,GUI类包含一个带有jtabbedpane的jframe,它有两个选项卡,第一个选项卡包含一个jtable,称为jtable1,第
以下代码产生错误 The nested query is not supported. Operation1='Case' Operation2='Collect' 问题是我做错了什么?我该如何解决?
我已经为 HA redis 集群(2 个副本、1 个主节点、3 个哨兵)设置了本地 docker 环境。只有哨兵暴露端口(10021、10022、10023)。 我使用的是 stackexchange
我正在 Desk.com 中构建一个“集成 URL”,它使用 Shopify Liquid 模板过滤器语法。对于开始日期为 7 天前而结束日期为现在的查询,此 URL 需要包含“开始日期”和“结束日期
你一定想过。然而情况却不理想,python中只能使用类似于 i++/i--等操作。 python中的自增操作 下面代码几乎是所有程序员在python中进行自增(减)操作的常用
我需要在每个使用 github 操作的手动构建中显示分支。例如:https://gyazo.com/2131bf83b0df1e2157480e5be842d4fb 我应该显示分支而不是一个。 最佳答
我有一个关于 Perl qr 运算符的问题: #!/usr/bin/perl -w &mysplit("a:b:c", /:/); sub mysplit { my($str, $patt
我已经使用 ArgoUML 创建了一个 ERD(实体关系图),我希望在一个类中创建两个操作,它们都具有 void 返回类型。但是,我只能创建一个返回 void 类型的操作。 例如: 我能够将 book
Github 操作仍处于测试阶段并且很新,但我希望有人可以提供帮助。我认为可以在主分支和拉取请求上运行 github 操作,如下所示: on: pull_request push: b
我正在尝试创建一个 Twilio 工作流来调用电话并记录用户所说的内容。为此,我正在使用 Record,但我不确定要在 action 参数中放置什么。 尽管我知道 Twilio 会发送有关调用该 UR
我不确定这是否可行,但值得一试。我正在使用模板缓冲区来减少使用此算法的延迟渲染器中光体积的过度绘制(当相机位于体积之外时): 使用廉价的着色器,将深度测试设置为 LEQUAL 绘制背面,将它们标记在模
有没有聪明的方法来复制 和 重命名 文件通过 GitHub 操作? 我想将一些自述文件复制到 /docs文件夹(:= 同一个 repo,不是远程的!),它们将根据它们的 frontmatter 重命名
我有一个 .csv 文件,其中第一列包含用户名。它们采用 FirstName LastName 的形式。我想获取 FirstName 并将 LastName 的第一个字符添加到它上面,然后删除空格。然
Sitecore 根据 Sitecore 树中定义的项目名称生成 URL, http://samplewebsite/Pages/Sample Page 但我们的客户有兴趣降低所有 URL(页面/示例
我正在尝试进行一些计算,但是一旦我输入金额,它就会完成。我只是希望通过单击按钮而不是自动发生这种情况。 到目前为止我做了什么: Angular JS - programming-fr
我的公司创建了一种在环境之间移动文件的复杂方法,现在我们希望将某些构建的 JS 文件(已转换和缩小)从一个 github 存储库移动到另一个。使用 github 操作可以实现这一点吗? 最佳答案 最简
在我的代码中,我创建了一个 JSONArray 对象。并向 JSONArray 对象添加了两个 JSONObject。我使用的是 json-simple-1.1.jar。我的代码是 package j
我是一名优秀的程序员,十分优秀!