SSM集成sharding-jdbc

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/long198861/article/details/82992177

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]

猜你喜欢

转载自blog.csdn.net/long198861/article/details/82992177