@@ -1,48 +1,76 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | <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"> | 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> | |||||
<modelVersion>4.0.0</modelVersion> | |||||
<artifactId>spring-boot-demo-sharding-jdbc</artifactId> | |||||
<artifactId>spring-boot-demo-sharding-jdbc</artifactId> | |||||
<version>1.0.0-SNAPSHOT</version> | |||||
<packaging>jar</packaging> | |||||
<name>spring-boot-demo-sharding-jdbc</name> | |||||
<description>Demo project for Spring Boot</description> | |||||
<parent> | |||||
<groupId>com.xkcoding</groupId> | |||||
<artifactId>spring-boot-demo</artifactId> | |||||
<version>1.0.0-SNAPSHOT</version> | <version>1.0.0-SNAPSHOT</version> | ||||
<packaging>jar</packaging> | |||||
<name>spring-boot-demo-sharding-jdbc</name> | |||||
<description>Demo project for Spring Boot</description> | |||||
<parent> | |||||
<groupId>com.xkcoding</groupId> | |||||
<artifactId>spring-boot-demo</artifactId> | |||||
<version>1.0.0-SNAPSHOT</version> | |||||
</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</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-test</artifactId> | |||||
<scope>test</scope> | |||||
</dependency> | |||||
</dependencies> | |||||
<build> | |||||
<finalName>spring-boot-demo-sharding-jdbc</finalName> | |||||
<plugins> | |||||
<plugin> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-maven-plugin</artifactId> | |||||
</plugin> | |||||
</plugins> | |||||
</build> | |||||
</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</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-test</artifactId> | |||||
<scope>test</scope> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.baomidou</groupId> | |||||
<artifactId>mybatis-plus-boot-starter</artifactId> | |||||
<version>3.1.0</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>mysql</groupId> | |||||
<artifactId>mysql-connector-java</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>io.shardingsphere</groupId> | |||||
<artifactId>sharding-jdbc-core</artifactId> | |||||
<version>3.1.0</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>cn.hutool</groupId> | |||||
<artifactId>hutool-all</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.projectlombok</groupId> | |||||
<artifactId>lombok</artifactId> | |||||
<optional>true</optional> | |||||
</dependency> | |||||
</dependencies> | |||||
<build> | |||||
<finalName>spring-boot-demo-sharding-jdbc</finalName> | |||||
<plugins> | |||||
<plugin> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-maven-plugin</artifactId> | |||||
</plugin> | |||||
</plugins> | |||||
</build> | |||||
</project> | </project> |
@@ -0,0 +1,68 @@ | |||||
USE `spring-boot-demo`; | |||||
DROP TABLE IF EXISTS `t_order_0`; | |||||
CREATE TABLE `t_order_0` | |||||
( | |||||
`id` BIGINT NOT NULL COMMENT '主键', | |||||
`user_id` BIGINT NOT NULL COMMENT '用户id', | |||||
`order_id` BIGINT NOT NULL COMMENT '订单id', | |||||
`remark` VARCHAR(200) DEFAULT '' COMMENT '备注', | |||||
primary key (`id`) | |||||
) ENGINE = InnoDB | |||||
DEFAULT CHARSET = utf8 COMMENT ='Spring Boot Demo 分库分表 系列示例表0'; | |||||
DROP TABLE IF EXISTS `t_order_1`; | |||||
CREATE TABLE `t_order_1` | |||||
( | |||||
`id` BIGINT NOT NULL COMMENT '主键', | |||||
`user_id` BIGINT NOT NULL COMMENT '用户id', | |||||
`order_id` BIGINT NOT NULL COMMENT '订单id', | |||||
`remark` VARCHAR(200) DEFAULT '' COMMENT '备注', | |||||
primary key (`id`) | |||||
) ENGINE = InnoDB | |||||
DEFAULT CHARSET = utf8 COMMENT ='Spring Boot Demo 分库分表 系列示例表1'; | |||||
DROP TABLE IF EXISTS `t_order_2`; | |||||
CREATE TABLE `t_order_2` | |||||
( | |||||
`id` BIGINT NOT NULL COMMENT '主键', | |||||
`user_id` BIGINT NOT NULL COMMENT '用户id', | |||||
`order_id` BIGINT NOT NULL COMMENT '订单id', | |||||
`remark` VARCHAR(200) DEFAULT '' COMMENT '备注', | |||||
primary key (`id`) | |||||
) ENGINE = InnoDB | |||||
DEFAULT CHARSET = utf8 COMMENT ='Spring Boot Demo 分库分表 系列示例表2'; | |||||
USE `spring-boot-demo-2`; | |||||
DROP TABLE IF EXISTS `t_order_0`; | |||||
CREATE TABLE `t_order_0` | |||||
( | |||||
`id` BIGINT NOT NULL COMMENT '主键', | |||||
`user_id` BIGINT NOT NULL COMMENT '用户id', | |||||
`order_id` BIGINT NOT NULL COMMENT '订单id', | |||||
`remark` VARCHAR(200) DEFAULT '' COMMENT '备注', | |||||
primary key (`id`) | |||||
) ENGINE = InnoDB | |||||
DEFAULT CHARSET = utf8 COMMENT ='Spring Boot Demo 分库分表 系列示例表0'; | |||||
DROP TABLE IF EXISTS `t_order_1`; | |||||
CREATE TABLE `t_order_1` | |||||
( | |||||
`id` BIGINT NOT NULL COMMENT '主键', | |||||
`user_id` BIGINT NOT NULL COMMENT '用户id', | |||||
`order_id` BIGINT NOT NULL COMMENT '订单id', | |||||
`remark` VARCHAR(200) DEFAULT '' COMMENT '备注', | |||||
primary key (`id`) | |||||
) ENGINE = InnoDB | |||||
DEFAULT CHARSET = utf8 COMMENT ='Spring Boot Demo 分库分表 系列示例表1'; | |||||
DROP TABLE IF EXISTS `t_order_2`; | |||||
CREATE TABLE `t_order_2` | |||||
( | |||||
`id` BIGINT NOT NULL COMMENT '主键', | |||||
`user_id` BIGINT NOT NULL COMMENT '用户id', | |||||
`order_id` BIGINT NOT NULL COMMENT '订单id', | |||||
`remark` VARCHAR(200) DEFAULT '' COMMENT '备注', | |||||
primary key (`id`) | |||||
) ENGINE = InnoDB | |||||
DEFAULT CHARSET = utf8 COMMENT ='Spring Boot Demo 分库分表 系列示例表2'; |
@@ -1,7 +1,10 @@ | |||||
package com.xkcoding.sharding.jdbc; | package com.xkcoding.sharding.jdbc; | ||||
import org.mybatis.spring.annotation.MapperScan; | |||||
import org.springframework.boot.SpringApplication; | import org.springframework.boot.SpringApplication; | ||||
import org.springframework.boot.autoconfigure.SpringBootApplication; | import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; | |||||
import org.springframework.transaction.annotation.EnableTransactionManagement; | |||||
/** | /** | ||||
* <p> | * <p> | ||||
@@ -17,6 +20,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||||
* @modified: yangkai.shen | * @modified: yangkai.shen | ||||
*/ | */ | ||||
@SpringBootApplication | @SpringBootApplication | ||||
@EnableTransactionManagement(proxyTargetClass = true) | |||||
@MapperScan("com.xkcoding.sharding.jdbc.mapper") | |||||
public class SpringBootDemoShardingJdbcApplication { | public class SpringBootDemoShardingJdbcApplication { | ||||
public static void main(String[] args) { | public static void main(String[] args) { | ||||
@@ -0,0 +1,91 @@ | |||||
package com.xkcoding.sharding.jdbc.config; | |||||
import com.zaxxer.hikari.HikariDataSource; | |||||
import io.shardingsphere.api.config.rule.ShardingRuleConfiguration; | |||||
import io.shardingsphere.api.config.rule.TableRuleConfiguration; | |||||
import io.shardingsphere.api.config.strategy.InlineShardingStrategyConfiguration; | |||||
import io.shardingsphere.api.config.strategy.NoneShardingStrategyConfiguration; | |||||
import io.shardingsphere.core.keygen.DefaultKeyGenerator; | |||||
import io.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory; | |||||
import org.springframework.beans.factory.annotation.Qualifier; | |||||
import org.springframework.context.annotation.Bean; | |||||
import org.springframework.context.annotation.Configuration; | |||||
import org.springframework.context.annotation.Primary; | |||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager; | |||||
import javax.sql.DataSource; | |||||
import java.sql.SQLException; | |||||
import java.util.HashMap; | |||||
import java.util.Map; | |||||
import java.util.Properties; | |||||
import java.util.concurrent.ConcurrentHashMap; | |||||
/** | |||||
* datetime 2018/11/28 10:46 | |||||
* | |||||
* @author sin5 | |||||
*/ | |||||
@Configuration | |||||
public class DataSourceShardingConfig { | |||||
/** | |||||
* 需要手动配置事务管理器 | |||||
*/ | |||||
@Bean | |||||
public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource) { | |||||
return new DataSourceTransactionManager(dataSource); | |||||
} | |||||
@Bean(name = "dataSource") | |||||
@Primary | |||||
public DataSource dataSource() throws SQLException { | |||||
ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration(); | |||||
// 设置分库策略 | |||||
shardingRuleConfig.setDefaultDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("user_id", "ds${user_id % 2}")); | |||||
// 设置规则适配的表 | |||||
shardingRuleConfig.getBindingTableGroups().add("t_order"); | |||||
// 设置分表策略 | |||||
shardingRuleConfig.getTableRuleConfigs().add(orderTableRule()); | |||||
shardingRuleConfig.setDefaultDataSourceName("ds0"); | |||||
shardingRuleConfig.setDefaultTableShardingStrategyConfig(new NoneShardingStrategyConfiguration()); | |||||
Properties properties = new Properties(); | |||||
properties.setProperty("sql.show", "true"); | |||||
return ShardingDataSourceFactory.createDataSource(dataSourceMap(), shardingRuleConfig, new ConcurrentHashMap<>(16), properties); | |||||
} | |||||
private TableRuleConfiguration orderTableRule() { | |||||
TableRuleConfiguration tableRule = new TableRuleConfiguration(); | |||||
// 设置逻辑表名 | |||||
tableRule.setLogicTable("t_order"); | |||||
// ds${0..1}.t_order_${0..2} 也可以写成 ds$->{0..1}.t_order_$->{0..1} | |||||
tableRule.setActualDataNodes("ds${0..1}.t_order_${0..2}"); | |||||
tableRule.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("order_id", "t_order_$->{order_id % 3}")); | |||||
tableRule.setKeyGenerator(new DefaultKeyGenerator()); | |||||
tableRule.setKeyGeneratorColumnName("order_id"); | |||||
return tableRule; | |||||
} | |||||
private Map<String, DataSource> dataSourceMap() { | |||||
Map<String, DataSource> dataSourceMap = new HashMap<>(16); | |||||
// 配置第一个数据源 | |||||
HikariDataSource ds0 = new HikariDataSource(); | |||||
ds0.setDriverClassName("com.mysql.cj.jdbc.Driver"); | |||||
ds0.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/spring-boot-demo?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8"); | |||||
ds0.setUsername("root"); | |||||
ds0.setPassword("root"); | |||||
// 配置第二个数据源 | |||||
HikariDataSource ds1 = new HikariDataSource(); | |||||
ds1.setDriverClassName("com.mysql.cj.jdbc.Driver"); | |||||
ds1.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/spring-boot-demo-2?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8"); | |||||
ds1.setUsername("root"); | |||||
ds1.setPassword("root"); | |||||
dataSourceMap.put("ds0", ds0); | |||||
dataSourceMap.put("ds1", ds1); | |||||
return dataSourceMap; | |||||
} | |||||
} |
@@ -0,0 +1,22 @@ | |||||
package com.xkcoding.sharding.jdbc.mapper; | |||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |||||
import com.xkcoding.sharding.jdbc.model.Order; | |||||
import org.springframework.stereotype.Component; | |||||
/** | |||||
* <p> | |||||
* 订单表 Mapper | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.sharding.jdbc.mapper | |||||
* @description: 订单表 Mapper | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2019-03-26 13:38 | |||||
* @copyright: Copyright (c) 2019 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
@Component | |||||
public interface OrderMapper extends BaseMapper<Order> { | |||||
} |
@@ -0,0 +1,45 @@ | |||||
package com.xkcoding.sharding.jdbc.model; | |||||
import com.baomidou.mybatisplus.annotation.TableName; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Builder; | |||||
import lombok.Data; | |||||
import lombok.NoArgsConstructor; | |||||
/** | |||||
* <p> | |||||
* 订单表 | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.sharding.jdbc.model | |||||
* @description: 订单表 | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2019-03-26 13:35 | |||||
* @copyright: Copyright (c) 2019 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
@Data | |||||
@NoArgsConstructor | |||||
@AllArgsConstructor | |||||
@Builder | |||||
@TableName(value = "t_order") | |||||
public class Order { | |||||
/** | |||||
* 主键 | |||||
*/ | |||||
private Long id; | |||||
/** | |||||
* 用户id | |||||
*/ | |||||
private Long userId; | |||||
/** | |||||
* 订单id | |||||
*/ | |||||
private Long orderId; | |||||
/** | |||||
* 备注 | |||||
*/ | |||||
private String remark; | |||||
} |
@@ -0,0 +1,3 @@ | |||||
mybatis-plus: | |||||
global-config: | |||||
banner: false |
@@ -1,17 +1,80 @@ | |||||
package com.xkcoding.sharding.jdbc; | package com.xkcoding.sharding.jdbc; | ||||
import cn.hutool.core.util.RandomUtil; | |||||
import cn.hutool.json.JSONUtil; | |||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||||
import com.xkcoding.sharding.jdbc.mapper.OrderMapper; | |||||
import com.xkcoding.sharding.jdbc.model.Order; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.junit.Test; | import org.junit.Test; | ||||
import org.junit.runner.RunWith; | import org.junit.runner.RunWith; | ||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.boot.test.context.SpringBootTest; | import org.springframework.boot.test.context.SpringBootTest; | ||||
import org.springframework.test.context.junit4.SpringRunner; | import org.springframework.test.context.junit4.SpringRunner; | ||||
import java.util.List; | |||||
/** | |||||
* <p> | |||||
* 测试sharding-jdbc分库分表 | |||||
* </p> | |||||
* | |||||
* @package: com.xkcoding.sharding.jdbc | |||||
* @description: 测试sharding-jdbc分库分表 | |||||
* @author: yangkai.shen | |||||
* @date: Created in 2019-03-26 13:44 | |||||
* @copyright: Copyright (c) 2019 | |||||
* @version: V1.0 | |||||
* @modified: yangkai.shen | |||||
*/ | |||||
@Slf4j | |||||
@RunWith(SpringRunner.class) | @RunWith(SpringRunner.class) | ||||
@SpringBootTest | @SpringBootTest | ||||
public class SpringBootDemoShardingJdbcApplicationTests { | public class SpringBootDemoShardingJdbcApplicationTests { | ||||
@Autowired | |||||
private OrderMapper orderMapper; | |||||
/** | |||||
* 测试新增 | |||||
*/ | |||||
@Test | |||||
public void testInsert() { | |||||
for (long i = 1; i < 10; i++) { | |||||
for (long j = 1; j < 20; j++) { | |||||
Order order = Order.builder().userId(i).orderId(j).remark(RandomUtil.randomString(20)).build(); | |||||
orderMapper.insert(order); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* 测试更新 | |||||
*/ | |||||
@Test | @Test | ||||
public void contextLoads() { | |||||
public void testUpdate() { | |||||
Order update = new Order(); | |||||
update.setRemark("修改备注信息"); | |||||
orderMapper.update(update, Wrappers.<Order>update().lambda().eq(Order::getOrderId, 2).eq(Order::getUserId, 2)); | |||||
} | } | ||||
/** | |||||
* 测试删除 | |||||
*/ | |||||
@Test | |||||
public void testDelete() { | |||||
orderMapper.delete(new QueryWrapper<>()); | |||||
} | |||||
/** | |||||
* 测试查询 | |||||
*/ | |||||
@Test | |||||
public void testSelect() { | |||||
List<Order> orders = orderMapper.selectList(Wrappers.<Order>query().lambda().in(Order::getOrderId, 1, 2)); | |||||
log.info("【orders】= {}", JSONUtil.toJsonStr(orders)); | |||||
} | |||||
} | } | ||||