Sharding-JDBC 按日期时间分库分表
简介
Sharding-JDBC
定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。
- 适用于任何基于Java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
- 基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
- 支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer和PostgreSQL。
集成sharding-jdbc
首先创建创建数据库和表这是sharding-jdbc所要求的。
create database db_201906;
create database db_201907; use db_201906;
create table t_order_20190614(id int not null auto_increment,order_no varchar(16) NOT NULL,sys_time datetime,PRIMARY KEY (id));
create table t_order_20190615(id int not null auto_increment,order_no varchar(16) NOT NULL,sys_time datetime,PRIMARY KEY (id));
insert into t_order_20190614 values(0,'','2019-06-14 0:0:0');
insert into t_order_20190615 values(0,'','2019-06-15 0:0:0'); use db_201907;
create table t_order_20190714(id int not null auto_increment,order_no varchar(16) NOT NULL,sys_time datetime,PRIMARY KEY (id));
create table t_order_20190715(id int not null auto_increment,order_no varchar(16) NOT NULL,sys_time datetime,PRIMARY KEY (id));
insert into t_order_20190714 values(0,'','2019-07-14 0:0:0');
insert into t_order_20190715 values(0,'','2019-07-15 0:0:0');
接着是pom.xml文件,添加sharding-jdbc到工程中,主要是下面两个依赖:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>org.osource.aurora</groupId>
<artifactId>shardingjdbc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>shardingjdbc</name>
<url>http://maven.apache.org</url> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties> <dependencies> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <!--sharding-jdbc -->
<dependency>
<groupId>io.shardingjdbc</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>2.0.3</version>
</dependency> <dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.3</version>
</dependency> </dependencies>
<build>
<plugins> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scm-plugin</artifactId>
<version>1.9.4</version>
<configuration>
<connectionType>developerConnection</connectionType>
</configuration>
</plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<releaseProfiles>release</releaseProfiles>
<autoVersionSubmodules>true</autoVersionSubmodules>
<tagBase>https://github.com/sharding/shardingjdbc-framework.git</tagBase>
<tagNameFormat>v@{project.version}</tagNameFormat>
</configuration>
</plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<skip>true</skip>
<aggregate>true</aggregate>
<charset>UTF-8</charset>
<encoding>UTF-8</encoding>
<docencoding>UTF-8</docencoding>
</configuration>
</plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/*.xml</exclude>
</excludes>
</configuration>
</plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- 设置成true在使用maven打包发布时不做junit测试 -->
<skip>true</skip>
</configuration>
</plugin> </plugins>
</build> </project>
首先是数据源配置和库策略、表策略:
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager; import io.shardingjdbc.core.api.config.ShardingRuleConfiguration;
import io.shardingjdbc.core.api.config.TableRuleConfiguration;
import io.shardingjdbc.core.api.config.strategy.StandardShardingStrategyConfiguration;
import io.shardingjdbc.core.jdbc.core.datasource.ShardingDataSource; @Configuration
public class ShardingDataSourceConfiguration { @Value("${spring.datasource.username:root}")
private String username; @Value("${spring.datasource.password:123456}")
private String password; @Value("${spring.datasource.url}")
private String jdbcUrl; @Value("${spring.datasource.driver-class-name}")
private String driverClassName; @Value("${shardingjdbc.sql.show:true}")
private String sqlShow; @Value("${mybatis.mapper-locations:mappper/**/*.xml}")
private String mapperLocations; // 配置sharding-jdbc的DataSource,给上层应用使用,这个DataSource包含所有的逻辑库和逻辑表,应用增删改查时,修改对应sql
// 然后选择合适的数据库继续操作。因此这个DataSource创建很重要。
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource shardingDataSource() throws SQLException { ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration(); // 订单表配置,可以累计添加多个配置
shardingRuleConfig.getTableRuleConfigs().add(getOrderTableRuleConfiguration());
// shardingRuleConfig.getTableRuleConfigs().add(getUserTableRuleConfiguration()); // 打印SQL
Properties props = new Properties();
props.put("sql.show", sqlShow); return new ShardingDataSource(shardingRuleConfig.build(createDataSourceMap()),
new ConcurrentHashMap<String, Object>(), props); } // 创建用户表规则
@Bean
TableRuleConfiguration getOrderTableRuleConfiguration() {
TableRuleConfiguration orderTableRuleConfig = new TableRuleConfiguration(); orderTableRuleConfig.setLogicTable("t_order");
orderTableRuleConfig.setLogicIndex("sys_time"); // 设置数据库策略,传入的是sys_time
orderTableRuleConfig.setDatabaseShardingStrategyConfig(
new StandardShardingStrategyConfiguration("sys_time", DatabaseShardingAlgorithm.class.getName()));
// 设置数据表策略,传入的是sys_time
orderTableRuleConfig.setTableShardingStrategyConfig(
new StandardShardingStrategyConfiguration("sys_time", TableShardingAlgorithm.class.getName())); // 设置数据节点,格式为dbxx.tablexx。这里的名称要和map的别名一致。下面两种方式都可以
// orderTableRuleConfig.setActualDataNodes("db_${0..1}.t_order_${0..1}");
orderTableRuleConfig.setActualDataNodes(
"db_201906.t_order_20190614,db_201906.t_order_20190615,db_201907.t_order_20190714,db_201907.t_order_20190715");
// 设置纵列名称
// orderTableRuleConfig.setKeyGeneratorColumnName("ID");
return orderTableRuleConfig;
} // 下面函数是获取数据源,即包含有多少个数据库,读入到系统中存放于map中
private Map<String, DataSource> createDataSourceMap() {
Map<String, DataSource> result = new HashMap<>();
result.put("db_201906",
createDataSource("jdbc:mysql://localhost:3306/db_201906?characterEncoding=utf8&useSSL=false"));
result.put("db_201907",
createDataSource("jdbc:mysql://localhost:3306/db_201907?characterEncoding=utf8&useSSL=false"));
return result;
} private DataSource createDataSource(final String jdbcUrl) {
// 使用默认连接池
BasicDataSource result = new BasicDataSource();
// 指定driver的类名,默认从jdbc url中自动探测
result.setDriverClassName(com.mysql.jdbc.Driver.class.getName());
// 设置数据库路径
result.setUrl(jdbcUrl);
// 设置数据库用户名
result.setUsername(username);
// 设置数据密码
result.setPassword(password);
return result;
} @Bean("sqlSessionFactory")
@Primary
public SqlSessionFactory sqlSessionFactory(DataSource shardingDataSource) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(shardingDataSource);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sessionFactory.setMapperLocations(resolver.getResources(mapperLocations));
return sessionFactory.getObject();
} /**
* - 需要手动配置事务管理器
*/
@Bean
public DataSourceTransactionManager transactitonManager(DataSource shardingDataSource) {
return new DataSourceTransactionManager(shardingDataSource);
} @Bean
public SqlSessionTemplate sqlSessionTmplate(SqlSessionFactory sqlSessionFactory) {
SqlSessionTemplate sqlSessionTmplate = new SqlSessionTemplate(sqlSessionFactory);
return sqlSessionTmplate;
} }
数据库分库策略 DatabaseShardingAlgorithm
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date; import io.shardingjdbc.core.api.algorithm.sharding.PreciseShardingValue;
import io.shardingjdbc.core.api.algorithm.sharding.standard.PreciseShardingAlgorithm; public class DatabaseShardingAlgorithm implements PreciseShardingAlgorithm<String> { @Override
public String doSharding(Collection<String> collection, PreciseShardingValue<String> preciseShardingValue) { String db_name = "db_";
try {
Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(preciseShardingValue.getValue());
String year = String.format("%tY", date);
String mon = String.format("%tm", date);
db_name = db_name + year + mon;
System.out.println("db_name:" + db_name);
} catch (ParseException e) {
e.printStackTrace();
} for (String each : collection) {
System.out.println("db:" + each);
if (each.equals(db_name)) {
return each;
}
} throw new IllegalArgumentException();
} }
数据表分表策略 TableShardingAlgorithm
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date; import io.shardingjdbc.core.api.algorithm.sharding.PreciseShardingValue;
import io.shardingjdbc.core.api.algorithm.sharding.standard.PreciseShardingAlgorithm; public class TableShardingAlgorithm implements PreciseShardingAlgorithm<String> { @Override
public String doSharding(Collection<String> collection, PreciseShardingValue<String> preciseShardingValue) {
String tb_name = preciseShardingValue.getLogicTableName() + "_";
try {
Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(preciseShardingValue.getValue());
String year = String.format("%tY", date);
String mon = String.format("%tm", date);
String dat = String.format("%td", date);
tb_name = tb_name + year + mon + dat;
System.out.println("tb_name:" + tb_name);
} catch (ParseException e) {
e.printStackTrace();
} for (String each : collection) {
System.out.println("t_order_:" + each);
if (each.equals(tb_name)) {
return each;
}
} throw new IllegalArgumentException(); } }
测试并使用sharding-jdbc
上面基本已经完成了sharding-jdbc的集成,下面将进行测试
创建实体类 Order
import java.io.Serializable; public class Order implements Serializable { /**
*
*/
private static final long serialVersionUID = -8759492936340749287L; private String orderNo; private String sysTime; public String getOrderNo() {
return orderNo;
} public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
} public String getSysTime() {
return sysTime;
} public void setSysTime(String sysTime) {
this.sysTime = sysTime;
} @Override
public String toString() {
return "Order [orderNo=" + orderNo + ", sysTime=" + sysTime + "]";
} }
创建服务接口类OrderService
import java.util.List; public interface OrderService { List<Order> getAll(String sysTime); }
创建服务接口类实现 OrderServiceImpl
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; @Service("orderService")
public class OrderServiceImpl implements OrderService { @Autowired
private OrderMapper orderMapper; @Override
public List<Order> getAll(String sysTime) {
return orderMapper.findAll(sysTime);
} }
创建 OrderMapper 数据访问层
import java.util.List; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select; @Mapper
public interface OrderMapper { @Select("select * from order where sys_time = #{sysTime}")
List<Order> findAll(@Param("sys_time") String sysTime); }
创建 Spring Boot 启动类 SpringBootApplicationTest
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan; @SpringBootApplication
//开启通用注解扫描
@ComponentScan(basePackages = { "org.shardingjdbc" })
@MapperScan(basePackages = { "org.shardingjdbc.mapper.user,org.shardingjdbc.mapper.order" })
@EnableAutoConfiguration
public class SpringBootApplicationTest { public static void main(String[] args) {
SpringApplication.run(SpringBootApplicationTest.class, args);
} }
RestController 测试代码
import java.util.List; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; @RestController
public class OrderController { @Autowired
@Qualifier("orderService")
private OrderService orderService; @RequestMapping("/get")
public String getOrder() {
List<Order> list = orderService.getAll("2019-06-14 0:0:0");
System.out.println(list);
return "OK";
} }
SpringBootTest 测试方法
import java.util.List; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; /**
* Unit test for simple App.
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBootApplicationTest.class)
@EnableAutoConfiguration
public class AppTest { @Autowired
@Qualifier("orderService")
private OrderService orderService; @Test
public void getOrder() {
List<Order> list = orderService.getAll("2019-06-14 0:0:0");
System.out.println(list);
} }
sharding-jdbc 分库分表实现方式到此基本完成
Sharding-JDBC 按日期时间分库分表的更多相关文章
- sharding demo 读写分离 U (分库分表 & 不分库只分表)
application-sharding.yml sharding: jdbc: datasource: names: ds0,ds1,dsx,dsy ds0: type: com.zaxxer.hi ...
- 海量数据分库分表方案(二)技术选型与sharding-jdbc实现
上一章已经讲述分库分表算法选型,本章主要讲述分库分表技术选型 文中关联上一章,若下文出现提及其时,可以点击 分库分表算法方案与技术选型(一) 主要讲述 框架比较 sharding-jdbc.zdal ...
- 采用Sharding-JDBC解决分库分表
源码:Sharding-JDBC(分库分表) 一.Sharding-JDBC介绍 1,介绍 Sharding-JDBC是当当网研发的开源分布式数据库中间件,从 3.0 开始Sharding-JDBC被 ...
- 分库分表后跨分片查询与Elastic Search
携程酒店订单Elastic Search实战:http://www.lvesu.com/blog/main/cms-610.html 为什么分库分表后不建议跨分片查询:https://www.jian ...
- 【大数据和云计算技术社区】分库分表技术演进&最佳实践笔记
1.需求背景 移动互联网时代,海量的用户每天产生海量的数量,这些海量数据远不是一张表能Hold住的.比如 用户表:支付宝8亿,微信10亿.CITIC对公140万,对私8700万. 订单表:美团每天几千 ...
- 分库分表技术演进&最佳实践
每个优秀的程序员和架构师都应该掌握分库分表,这是我的观点. 移动互联网时代,海量的用户每天产生海量的数量,比如: 用户表 订单表 交易流水表 以支付宝用户为例,8亿:微信用户更是10亿.订单表更夸张, ...
- Sharding-JDBC分库分表简单示例
1. 简介 Sharding是一个简单的分库分表中间件,它不需要依赖于其他的服务,即可快速应用在实际项目的分库分表策略中. 2. 初始化数据库(db0.db1.db2) 1 #创建数据库db0 2 C ...
- Sharding JDBC整合SpringBoot 2.x 和 MyBatis Plus 进行分库分表
Sharding JDBC整合SpringBoot 2.x 和 MyBatis Plus 进行分库分表 交易所流水表的单表数据量已经过亿,选用Sharding-JDBC进行分库分表.MyBatis-P ...
- 数据库分库分表(sharding)系列【转】
原文地址:http://www.uml.org.cn/sjjm/201211212.asp数据库分库分表(sharding)系列 目录; (一) 拆分实施策略和示例演示 (二) 全局主键生成策略 (三 ...
随机推荐
- resfframework中修改序列化类的返回值
在序列化类中重写to_representation(self,instance)方法,这个是返回json对象的方法,返回的是一个待序列化的对象,可以直接对这个类进行定制,有关关联查询也可以在这里进行定 ...
- selenium 定位元素方法
1.通过id定位元素 写法1: element = driver.find_element_by_id("kw") 写法2: from selenium.webdriver.com ...
- Linux 各系统目录作用及内容
- BIND 主从配置
BIND 主从配置 环境:master:172.31.182.144slave:172.31.182.147 一.安装yum install bind bind-chroot -y 二.master ...
- sqlzoo易错题
https://sqlzoo.net/wiki/SELECT_names 答案在:https://github.com/codyloyd/sqlzoo-solutions/blob/master/SQ ...
- spring cloud (一) 服务注册中心 Eueka
1 pom.xml 添加依赖包 <dependency> <groupId>org.springframework.cloud</groupId> <arti ...
- python为什么要使用闭包
为什么要使用闭包 闭包避免了使用全局变量,此外,闭包允许将函数与其所操作的某些数据(环境)关连起来.这一点与面向对象编程是非常类似的,在面对象编程中,对象允许我们将某些数据(对象的属性)与一个或者多个 ...
- python测试开发django-rest-framework-61.权限认证(permission)
前言 用户登录后,才有操作当前用户的权限,不能操作其它人的用户,这就是需要用到权限认证,要不然你登录自己的用户,去操作别人用户的相关数据,就很危险了. authentication是身份认证,判断当前 ...
- clause
clause 英 [klɔːz] 美 [klɔz] 口语练习 跟读 n. 条款:[计] 子句 specify 英 ['spesɪfaɪ] 美 ['spɛsɪfaɪ] 口语练习 跟读 vt. 指 ...
- MyBatis框架的insert节点-向数据库中插入数据
需求:使用mybatis框架中的insert元素节点向数据库中插入数据 UserMapper.xml UserMapper.java 编写测试方法: @Test public void testAdd ...