網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
廢話(huà)不多說(shuō),上代碼!
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.0-RC1</version>
</dependency>
關(guān)鍵配置yml
spring:
#shardingjdbc主要配置
main:
allow-bean-definition-overriding: true #Bean覆蓋,srpingboot2.1以上默認(rèn)是false,一個(gè)實(shí)體類(lèi)對(duì)應(yīng)多張表,水平分表必須加
shardingsphere:
datasource:
names: h1 #單數(shù)據(jù)源,多個(gè)以逗號(hào)隔開(kāi)
h1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://rm-.mysql.cn-chengdu.rds.aliyuncs.com:3306/chen
username: chen
password: chen
sharding:
# binding-tables: hss_history #綁定表,需要關(guān)聯(lián)查詢(xún)的時(shí)候配置
tables:
hss_history: #邏輯表 下面是節(jié)點(diǎn)表,分表后還有數(shù)據(jù)在原來(lái)的表,所有查詢(xún)節(jié)點(diǎn)需要加上原來(lái)的表
actual-data-nodes: h1.hss_history,h1.hss_history_202$->{201..204}
key-generator: #主鍵生成策略 雪花算法,
column: id
type: SNOWFLAKE
table-strategy:
standard: #分片策略 以創(chuàng)建時(shí)候分表,實(shí)現(xiàn)類(lèi)計(jì)算
sharding-column: create_time
#對(duì)應(yīng)下面的分表策略類(lèi)
precise-algorithm-class-name: work.chen.history.config.TableShardingAlgorithm
range-algorithm-class-name: work.chen.history.config.TableShardingAlgorithm
#多數(shù)據(jù)源指定默認(rèn)數(shù)據(jù)源,兩個(gè)數(shù)據(jù)源其中一個(gè)數(shù)據(jù)源不參于分表可以設(shè)置
#default-data-source-name: h1
props:
sql: #展示SQL 測(cè)試的時(shí)候可以改為true
show: false
actual-data-nodes: h1.hss_history,h1.hss_history_202$->{201…204}
這代表可以查詢(xún)的表,有多少表就配多少,原始表hss_history,還有hss_history_202201-202204
如果這里配的節(jié)點(diǎn)表,數(shù)據(jù)庫(kù)中不存在,那么查詢(xún)的時(shí)候就會(huì)報(bào)錯(cuò) 找不到表,需要提前創(chuàng)建好表,
配了shardingjdbc 有些sql語(yǔ)句就不支持了,
SQL支持查詢(xún)
解決這個(gè)辦法,只有分多個(gè)數(shù)據(jù)源,不參于分表的數(shù)據(jù)源改為默認(rèn)的就不會(huì)使用sharding的數(shù)據(jù)源
分表具體策略
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;
import work.chenshuang.history.service.impl.HssHistoryService;
import work.chenshuang.history.utils.DateUtil;
import java.awt.image.ImageConsumer;
import java.util.Collection;
import java.util.Date;
import java.util.List;
// 分表規(guī)則
//按單月分表
public class TableShardingAlgorithm implements PreciseShardingAlgorithm<Date>,RangeShardingAlgorithm<Long> {
//@Autowired不能注入
private static HssHistoryService hssHistory = (HssHistoryService) SpringUtil.getBean(HssHistoryService.class);
//精確插入表名 單表
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Date> preciseShardingValue) {
StringBuffer tableName = new StringBuffer();
//表名精確匹配,表名加上截取的年月
tableName.append(preciseShardingValue.getLogicTableName())
//時(shí)間戳轉(zhuǎn)成date類(lèi)型
.append("_").append(DateUtil.date2Str(preciseShardingValue.getValue(), DateUtil.YEAR_MONTH_NUMBER));
// System.out.println("表名為:"+tableName.toString());
// System.out.println("邏輯表名"+preciseShardingValue.getLogicTableName());
System.out.println("時(shí)間"+preciseShardingValue.getValue());
//availableTargetNames存的是節(jié)點(diǎn)表名字,可以查詢(xún)的表
//單數(shù)據(jù)源這里就會(huì)有問(wèn)題,sql有問(wèn)題 @Select("select table_name from information_schema.tables where TABLE_SCHEMA=(select database())")
//List<String> tableNames = hssHistory.queryTableNames();
//創(chuàng)建表
//hssHistory.createTable(tableName.toString());
return tableName.toString();
}
@Override
public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Long> shardingValue) {
return null;
}
}
時(shí)間工具類(lèi)
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
@Slf4j
public class DateUtil {
public static final String DATE_FORMAT_DEFAULT = "yyyy-MM-dd HH:mm:ss";
public static final String DATE_FORMAT_NUMBER = "yyyyMMddHHmmss";
public static final String YEAR_MONTH_DAY_NUMBER = "yyyyMMdd";
public static final String YEAR_MONTH_NUMBER = "yyyyMM";
public static final String DATE_FORMAT_DAY_PATTERN = "yyyy-MM-dd";
public static final String YEAR_MONTH_DAY_EN_SECOND = "yyyy/MM/dd HH:mm:ss";
public static final String YEAR_MONTH_DAY_CN_SECOND = "yyyy年MM月dd日 HH時(shí)mm分ss秒";
public static final String YEAR_MONTH_DAY_CN = "yyyy年MM月dd日";
/**
* 采用 ThreadLocal 避免 SimpleDateFormat 非線(xiàn)程安全的問(wèn)題
* <p>
* Key —— 時(shí)間格式
* Value —— 解析特定時(shí)間格式的 SimpleDateFormat
*/
private static ThreadLocal<Map<String, SimpleDateFormat>> sThreadLocal = new ThreadLocal<>();
/**
* 獲取解析特定時(shí)間格式的 SimpleDateFormat
*
* @param pattern 時(shí)間格式
*/
private static SimpleDateFormat getDateFormat(String pattern) {
if (StringUtils.isBlank(pattern)) {
pattern = DATE_FORMAT_DEFAULT;
}
Map<String, SimpleDateFormat> strDateFormatMap = sThreadLocal.get();
if (strDateFormatMap == null) {
strDateFormatMap = new HashMap<>();
}
SimpleDateFormat simpleDateFormat = strDateFormatMap.get(pattern);
if (simpleDateFormat == null) {
simpleDateFormat = new SimpleDateFormat(pattern, Locale.getDefault());
strDateFormatMap.put(pattern, simpleDateFormat);
sThreadLocal.set(strDateFormatMap);
}
return simpleDateFormat;
}
public static Date toDate(LocalDateTime dateTime) {
if (dateTime == null) {
return null;
}
return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
}
public static String format(LocalDateTime dateTime, String format) {
if (dateTime == null) {
return null;
}
return dateTime.format(DateTimeFormatter.ofPattern(format));
}
public static LocalDateTime parse(String dateTimeStr, String format) {
if (StringUtils.isBlank(format)) {
format = DATE_FORMAT_DEFAULT;
}
if (dateTimeStr == null) {
return null;
}
DateTimeFormatter sf = DateTimeFormatter.ofPattern(format);
LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr, sf);
return dateTime;
}
public static String format(LocalDateTime dateTime) {
return format(dateTime, DATE_FORMAT_DEFAULT);
}
public static LocalDateTime parse(String dateTimeStr) {
return parse(dateTimeStr, DATE_FORMAT_DEFAULT);
}
// #############################################################################
/**
* 時(shí)間格式轉(zhuǎn)換為字符串格式
*
* @param date 時(shí)間
* @param format 格式 如("yyyy-MM-dd hh:mm:ss")
* @return String
*/
public static String date2Str(Date date, String format) {
if (StringUtils.isBlank(format)) {
format = DATE_FORMAT_DEFAULT;
}
if (date == null) {
return null;
}
return getDateFormat(format).format(date);
}
/**
* 字符串格式轉(zhuǎn)換為時(shí)間格式
*
* @param dateStr 字符串
* @param format 格式 如("yyyy-MM-dd HH:mm:ss")
* @return Date
*/
public static Date str2Date(String dateStr, String format) {
if (StringUtils.isBlank(format)) {
format = DATE_FORMAT_DEFAULT;
}
if (StringUtils.isBlank(dateStr)) {
return null;
}
try {
return getDateFormat(format).parse(dateStr);
} catch (ParseException pe) {
log.error("str2Date ParseException error", pe);
}
return null;
}
public static Date dateFormat(Date date, String format) {
if (StringUtils.isBlank(format)) {
format = DATE_FORMAT_DEFAULT;
}
if (date == null) {
return null;
}
return str2Date(date2Str(date, format), format);
}
/**
* @param timestamp:時(shí)間
*/
public static Date parse(long timestamp) {
return new Date(timestamp);
}
/**
* 獲取當(dāng)前日期
*
* @param pattern 格式如:yyyy-MM-dd
* @return
*/
public static String getCurrentDate(String pattern) {
return getDateFormat(pattern).format(new Date());
}
/**
* get cuurent Date return java.util.Date type
*/
public static Date getCurrentDate() {
return new Date();
}
/**
* get current Date return java.sql.Date type
*
* @return
*/
public static java.sql.Date getNowSqlDate() {
return new java.sql.Date(System.currentTimeMillis());
}
/**
* get the current timestamp return java.sql.Timestamp
*
* @return
*/
public static Timestamp getNowTimestamp() {
return new Timestamp(System.currentTimeMillis());
}
public static String timestamp2Str(Timestamp time, String format) {
return getDateFormat(format).format(time);
}
public static Date timestamp2Date(Timestamp time, String format) throws ParseException {
return str2Date(timestamp2Str(time, format), format);
}
public static Timestamp str2Timestamp(Timestamp time, String format) throws ParseException {
Date date = str2Date(timestamp2Str(time, format), format);
return new Timestamp(date.getTime());
}
public static Timestamp date2Timestamp(Date date, String format) {
Date result = str2Date(date2Str(date, format), format);
return new Timestamp(result.getTime());
}
/**
* time1>time2 返回正數(shù)
*
* @param time1
* @param time2
* @return
*/
public static long getOffsetBetweenTimes(String time1, String time2) {
return str2Date(time1, DATE_FORMAT_DEFAULT).getTime() - str2Date(time2, DATE_FORMAT_DEFAULT).getTime();
}
/**
* 返回時(shí)間差
*
* @param start
* @param end
* @param timeUnit 天d, 時(shí)h, 分m, 秒s
* @return 根據(jù)timeUnit返回
*/
public static long getOffsetBetweenDate(Date start, Date end, char timeUnit) {
long startT = start.getTime(); //定義上機(jī)時(shí)間
long endT = end.getTime(); //定義下機(jī)時(shí)間
long ss = (startT - endT) / (1000); //共計(jì)秒數(shù)
int mm = (int) ss / 60; //共計(jì)分鐘數(shù)
int hh = (int) ss / 3600; //共計(jì)小時(shí)數(shù)
int dd = hh / 24; //共計(jì)天數(shù)
System.out.println("######################## 共" + dd + "天 準(zhǔn)確時(shí)間是:" + hh + " 小時(shí) " + mm + " 分鐘" + ss + " 秒 共計(jì):" + ss * 1000 + " 毫秒");
long result = 0L;
if ('d' == timeUnit) {
result = dd;
} else if ('h' == timeUnit) {
result = hh;
} else if ('m' == timeUnit) {
result = mm;
} else if ('s' == timeUnit) {
result = ss;
}
return result;
}
/**
* 對(duì)指定日期滾動(dòng)指定天數(shù),負(fù)數(shù)時(shí),則往前滾,正數(shù)時(shí),則往后滾
*
* @param date Date
* @param days int
* @return String
*/
public static String rollDays(Date date, int days) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.DATE, days);
return date2Str(calendar.getTime(), DATE_FORMAT_DEFAULT);
}
/**
* 對(duì)指定日期滾動(dòng)指定分鐘,負(fù)數(shù)時(shí),則往前滾,正數(shù)時(shí),則往后滾
*
* @param date Date
* @param minutes int
* @return String
*/
public static String rollMinutes(Date date, int minutes) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.MINUTE, minutes);
return date2Str(calendar.getTime(), DATE_FORMAT_DEFAULT);
}
/**
* 對(duì)指定日期滾動(dòng)指定分鐘,負(fù)數(shù)時(shí),則往前滾,正數(shù)時(shí),則往后滾
*
* @param date Date
* @param seconds int
* @return String
*/
public static String rollSeconds(Date date, int seconds, String format) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.SECOND, seconds);
return date2Str(calendar.getTime(), format);
}
/**
* 返回 2013-01-16T06:24:26.829Z 時(shí)間
*
* @param date
* @return
* @throws Exception
*/
public static XMLGregorianCalendar getXmlDatetime(Date date) throws Exception {
if (null == date) {
date = new Date();
}
GregorianCalendar nowGregorianCalendar = new GregorianCalendar();
XMLGregorianCalendar xmlDatetime = DatatypeFactory.newInstance().newXMLGregorianCalendar(nowGregorianCalendar);
// XMLGregorianCalendar ->GregorianCalendar
nowGregorianCalendar = xmlDatetime.toGregorianCalendar();
nowGregorianCalendar.setTime(date);
return xmlDatetime;
}
public static boolean checkDateBettwenBoth(Date checkDate, Date date1, Date date2) {
boolean temp = false;
if (checkDate == null || date1 == null || date2 == null) {
temp = false;
return temp;
}
if (checkDate.equals(date1) || checkDate.equals(date2)) {
temp = true;
}
if (checkDate.after(date1) && checkDate.before(date2)) {
temp = true;
}
return temp;
}
public static String getFormatDatetime() throws Exception {
GregorianCalendar gCalendar = new GregorianCalendar();
String strDateTime;
try {
strDateTime = getDateFormat(DATE_FORMAT_DEFAULT).format(gCalendar.getTime());
} catch (Exception ex) {
System.out.println("Error Message:".concat(String.valueOf(String.valueOf(ex.toString()))));
String s = null;
return s;
}
return strDateTime;
}
/**
* 判斷給定的日期是一年中的第幾天
*
* @param dateTimeStr
* @return
*/
public static int dayOfYear(String dateTimeStr) {
int day = 0;
if (StringUtils.isBlank(dateTimeStr)) {
return day;
}
Date dateTime = str2Date(dateTimeStr, DATE_FORMAT_DEFAULT);
return dayOfYear(dateTime);
}
/**
* 判斷給定的日期是一年中的第幾天
*
* @param dateTime
* @return
*/
public static int dayOfYear(Date dateTime) {
int year = 0, month = 0, date = 0, day = 0;
if (null == dateTime) {
return day;
}
String dateTimeStr = date2Str(dateTime, null);
LocalDateTime localDateTime = parse(dateTimeStr);
year = localDateTime.getYear();
month = localDateTime.getMonthValue();
date = localDateTime.getDayOfMonth();
return dayOfYear(year, month, date);
}
/**
* 判斷給定的日期是一年中的第幾天
*
* @param year
* @param month
* @param date
* @return
*/
public static int dayOfYear(int year, int month, int date) {
int[] days = {0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int day = 0;
//判斷是不是閏年,然后設(shè)置二月的天數(shù)
if ((year % 400 == 0) || ((year % 100 != 0) && (year % 4 == 0))) {
days[2] = 29;
} else {
days[2] = 28;
}
for (int i = 1; i < month; i++) {
day += days[i];
}
day += date;
return day;
}
/*public static void main(String[] args){
System.out.print(new Date());
}*/
}
上面這個(gè)工具類(lèi)不導(dǎo)依賴(lài)會(huì)報(bào)錯(cuò)
<!-- sfl4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
注入工具類(lèi)
package work.chenshuang.history.config;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
public SpringUtil() {
}
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
if (applicationContext == null) {
applicationContext = arg0;
}
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static void setAppCtx(ApplicationContext webAppCtx) {
if (webAppCtx != null) {
applicationContext = webAppCtx;
}
}
/**
* 拿到ApplicationContext對(duì)象實(shí)例后就可以手動(dòng)獲取Bean的注入實(shí)例對(duì)象
*/
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
public static <T> T getBean(String name, Class<T> clazz) throws ClassNotFoundException {
return getApplicationContext().getBean(name, clazz);
}
public static final Object getBean(String beanName) {
return getApplicationContext().getBean(beanName);
}
public static final Object getBean(String beanName, String className) throws ClassNotFoundException {
Class clz = Class.forName(className);
return getApplicationContext().getBean(beanName, clz.getClass());
}
public static boolean containsBean(String name) {
return getApplicationContext().containsBean(name);
}
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
return getApplicationContext().isSingleton(name);
}
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
return getApplicationContext().getType(name);
}
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
return getApplicationContext().getAliases(name);
}
}
配置完就可以使用了 提前創(chuàng)建好表就行了 ,動(dòng)態(tài)創(chuàng)建表可以,但節(jié)點(diǎn)表沒(méi)法動(dòng)態(tài)改變,節(jié)點(diǎn)表不改變,查詢(xún)就只會(huì)查那配置好的表,有懂的大佬還望告知!
原文鏈接:https://blog.csdn.net/weixin_51216079/article/details/122670250
相關(guān)推薦
- 2022-08-28 linux應(yīng)用參數(shù)保存與配置
- 2022-04-15 玩數(shù)據(jù)必備Python庫(kù)之numpy使用詳解_python
- 2022-05-20 springboot-mybatis實(shí)現(xiàn)增刪改查
- 2022-02-27 jwt Claims token 秘鑰稍有不同也能解析成功 signWith setSigningK
- 2022-07-22 防火墻.iptables-tcp-flags防止nmap端口掃描
- 2022-10-12 Redis的共享session應(yīng)用實(shí)現(xiàn)短信登錄_Redis
- 2022-12-03 詳解QML?調(diào)用?C++?中的內(nèi)容_C 語(yǔ)言
- 2023-01-15 React報(bào)錯(cuò)Too?many?re-renders解決_React
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支