SSM集成sharding-jdbc
1.添加maven依赖
<properties>
<sharding-jdbc.version>1.4.0</sharding-jdbc.version>
</properties>
<!-- 引入sharding-jdbc核心模块 -->
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>${sharding-jdbc.version}</version>
</dependency>
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-config-common</artifactId>
<version>${sharding-jdbc.version}</version>
</dependency>
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-config-yaml</artifactId>
<version>${sharding-jdbc.version}</version>
</dependency>
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-config-spring</artifactId>
<version>${sharding-jdbc.version}</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
2.数据库脚本准备
创建订单表 t_order
DROP TABLE IF EXISTS `t_order`;
CREATE TABLE `t_order` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`create_time` datetime DEFAULT NULL comment '创建时间',
`order_no` VARCHAR(40) DEFAULT NULL COMMENT '订单编号',
`amount` DECIMAL(22,4) DEFAULT 0 COMMENT '金额',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
alter table t_order comment ' 订单表';
CREATE TABLE t_order_201801 LIKE t_order;
CREATE TABLE t_order_201802 LIKE t_order;
..
CREATE TABLE t_order_201812 LIKE t_order;
在t_order_201810中插入一条数据,日期是2018年10月的任意时间即可
3 准备2个配置文件 spring-datasource.xml spring-sharding.xml
spring容器启动的时候加载这个配置文件
spring-datasource.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="db_1" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc_driverClassName}" />
<property name="url" value="${jdbc_url}" />
<property name="username" value="${jdbc_username}" />
<property name="password" value="${jdbc_password}" />
<property name="minIdle" value="0" />
</bean>
<bean id="db_2" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc_driverClassName}" />
<property name="url" value="${jdbc_url}" />
<property name="username" value="${jdbc_username}" />
<property name="password" value="${jdbc_password}" />
<property name="minIdle" value="0" />
</bean>
</beans>
说明:这两个数据源都是指向同一个数据库,用来做演示而已
#------mysql-----
jdbc_driverClassName=com.mysql.jdbc.Driver
jdbc_url=jdbc:mysql://localhost:3306/luo
jdbc_username=root
jdbc_password=123456
spring-sharing.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:rdb="http://www.dangdang.com/schema/ddframe/rdb"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.dangdang.com/schema/ddframe/rdb http://www.dangdang.com/schema/ddframe/rdb/rdb.xsd ">
<rdb:strategy id="orderDatabaseStrategy" sharding-columns="create_date" algorithm-class="com.luolong.common.util.sharding.orderDatabaseShardingAlgorithm"/>
<rdb:strategy id="orderTableStrategy" sharding-columns="create_date" algorithm-class="com.luolong.common.util.sharding.orderTableShardingAlgorithm"/>
<rdb:data-source id="dataSource">
<rdb:sharding-rule default-data-source="db_1" data-sources="db_1,db_2">
<rdb:table-rules>
<rdb:table-rule logic-table="t_order" actual-tables="
t_order_201801,t_order_201802,t_order_201803,t_order_201804,t_order_201805,t_order_201806,
t_order_201807,t_order_201808,t_order_201809,t_order_201810,t_order_201811,t_order_201812"
database-strategy="orderDatabaseStrategy" table-strategy="orderTableStrategy"/>
</rdb:table-rules>
<rdb:default-database-strategy sharding-columns="none"algorithm-class="com.dangdang.ddframe.rdb.sharding.api.strategy.database.NoneDatabaseShardingAlgorithm"/>
<rdb:default-table-strategy sharding-columns="none" algorithm-class="com.dangdang.ddframe.rdb.sharding.api.strategy.table.NoneTableShardingAlgorithm"/>
</rdb:sharding-rule>
<rdb:props>
<prop key="metrics.enable">false</prop>
</rdb:props>
</rdb:data-source>
</beans>
说明:上面配置文件中有2个核心类 orderDatabaseShardingAlgorithm,orderTableShardingAlgorithm
orderDatabaseShardingAlgorithm 分库策略类 分库字段是create_date 与数据库的字段是一样的
orderTableShardingAlgorithm 分表策略类 分库字段是create_date 与数据库的字段是一样的
4.分库策略类和分表策略类
orderDatabaseShardingAlgorithm.java
public class orderDatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<Comparable<?>>{
private final static Logger logger = LoggerFactory.getLogger(orderDatabaseShardingAlgorithm.class);
/**
* 查询默认数据库
* 不实现接口可能会导致找不到数据源或查询多个数据库的数据
*/
@Override
public String doEqualSharding(Collection<String> availableTargetNames,ShardingValue<Comparable<?>> shardingValue) {
return "db_1";
}
@Override
public Collection<String> doInSharding(Collection<String> availableTargetNames,ShardingValue<Comparable<?>> shardingValue) {
Set<String> databaseSet = new HashSet<String>();
databaseSet.add("db_1");
return databaseSet;
}
@Override
public Collection<String> doBetweenSharding(Collection<String> availableTargetNames,ShardingValue<Comparable<?>> shardingValue) {
Set<String> databaseSet = new HashSet<String>();
databaseSet.add("db_1");
return databaseSet;
}
orderTableShardingAlgorithm.java
public class orderTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Comparable<?>>{
private final static Logger logger = LoggerFactory.getLogger(orderTableShardingAlgorithm.class);
@Override
public Collection<String> doBetweenSharding(Collection<String> arg0,ShardingValue<Comparable<?>> arg1){
Set<String> result = new HashSet<String>();
String[] createDate = null;
List<String> dateList = new ArrayList<String>();
try{
if(StringUtils.equals("create_date", arg1.getColumnName())){
createDate = arg1.getValueRange().toString().replaceAll("\\[", "").replaceAll("\\]", "").trim().split("‥");
if (null != createDate && createDate.length > 0) {
dateList = DateUtils.getMonthBetween(createDate[0], createDate[1]);
if (dateList.size() > 0) {
for (String date : dateList) {
StringBuffer tableName = new StringBuffer(arg1.getLogicTableName());
tableName.append("_").append(date.replace("-", ""));
result.add(tableName.toString());
}
}
}else{
logger.error("时间是必须的分表字段!");
}
}
}catch(Exception e){
logger.error("分表规则计算错误。");
logger.error(e.getMessage(),e);
}
return result;
}
@Override
public String doEqualSharding(Collection<String> arg0,ShardingValue<Comparable<?>> arg1){
String createDate = "";
StringBuffer tableName = new StringBuffer(arg1.getLogicTableName());
try{
if(StringUtils.equals("create_date", arg1.getColumnName())){
createDate = arg1.getValue().toString();
}
if(StringUtils.isNotEmpty(createDate)){
tableName.append("_").append(DateUtil.format(DateUtil.start2Date(createDate), "yyyyMM"));
}else{
logger.error("时间是必须的分表字段!");
}
}catch(Exception e){
logger.error("分表规则计算错误。");
logger.error(e.getMessage(),e);
}
return tableName.toString();
}
@Override
public Collection<String> doInSharding(Collection<String> arg0,ShardingValue<Comparable<?>> arg1){
return null;
}
5.orderMapper.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.luolong.dao.OrderDao">
<select id="getPage" parameterType="com.luolong.util.dialect.Page" resultType="com.luolong.model.Order">
SELECT id,
order_no orderNo,
create_date createDate,
amount
FROM t_order
<where>
<if test="order.startTime != null and order.startTime !='' and order.endTime != null and order.endTime != ''">
and create_date between #{order.startTime} and #{order.endTime}
</if>
</where>
</select>
</mapper>
注意:上面的sql中表名我并没有指定具体表名 是t_order
结果:当你调用者个sql时,依据create_date走分库分表策略,会改写你的sql
以下是控制台打印
Preparing: SELECT id, order_no orderNo, create_date createDate, amount FROM t_order WHERE create_date between ? and ? limit 0 ,15
Parameters: 2018-10-01 08:51:03(String), 2018-10-10 08:51:08(String) ---- 入参
After database sharding t_order result: [db_1] ---数据源
After table sharding t_order result: [t_order_201810] -- 表名
最后变成
db_1: SELECT id, order_no AS orderNo, create_date AS createDate, amount FROM t_order_201810 WHERE create_date BETWEEN ? AND ? LIMIT 0, 15 [2018-10-01 08:51:03, 2018-10-10 08:51:08]