springboot简单的分表插件

本文介绍了一种基于SpringBoot、MyBatis和jsqlparser实现的简单分表插件。通过拦截SQL,分析并替换表名,支持CRUD和JOIN操作的分表。主要涉及分表注解、策略模式、SQL重写以及MyBatis拦截器的使用,实现了在没有中间件的情况下,降低分表学习和使用成本。
摘要由CSDN通过智能技术生成

业务上做了水平分表,公司基础架构没有提供分表中间件,开源的中间件用起来门槛高,有较大的学习成本。自己基于springboot+mybatis+jsqlparser实现了一个简单的分表插件。
笼统来说就是拦截SQL,分析SQL,替换tableName,返回重写后的SQL给Mybatis支持简单的CRUD分表,支持join分表
项目里引入maven依赖:

 		<dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>x.x.x</version>
        </dependency>
		<dependency>
            <groupId>com.github.jsqlparser</groupId>
            <artifactId>jsqlparser</artifactId>
            <version>x.x.x</version>
        </dependency>

1.分表注解

首先需要一个注解,用来标识需要分表的类或方法。

@Retention(RetentionPolicy.RUNTIME)
@Target({
   ElementType.TYPE, ElementType.METHOD})
public @interface TableSplit {
   

    //是否分表
    boolean split() default true;

    //表名 该字段暂未使用。使用注解会对SQL中所有的表名进行替换
    String table() default "";

    //分表字段 
    String field() default "";

    //分表策略
    String strategy() default "";

}

2.分表策略

用策略模式设计一个分表的策略,在后续的mybatis拦截器中使用

2.1策略接口

public interface Strategy {
   

    String TABLE_NAME = "table_name";
    String SPLIT_FIELD = "split_field";
    String EXECUTE_PARAM_DECLARE = "execute_param_declare";
    String EXECUTE_PARAM_VALUES = "execute_param_values";

    /**
     * convert sql
     * @param params
     * @return
     * @throws Exception
     */
    String convert(String sql, Map<String, Object> params) throws Exception;

    /**
     * 
     * @param params
     * @return
     * @throws Exception
     */
    Integer getTableIndex(Map<String, Object> params) throws Exception;
}

2.2 分表策略管理类

管理类维护一个map,可以通过key获取不同的分表策略。

@Slf4j
public class StrategyManager {
   

    private Map<String, Strategy> strategies = new ConcurrentHashMap<>(10);

    public Strategy getStrategy(String key) {
   
        return strategies.get(key);
    }

    public Map<String, Strategy> getStrategies() {
   
        return strategies;
    }

    public void setStrategies(Map<String, String> strategies) {
   
        for (Map.Entry<String, String> entry : strategies.entrySet()) {
   
            try {
   
                this.strategies.put(entry.getKey(), (Strategy) Class.forName(entry.getValue()).newInstance());
            } catch (Exception e) {
   
                log.error("实例化策略出错", e);
            }
        }
    }
}

2.3 分表策略的实现

分表策略的具体实现可以根据实际场景和业务自行实现,比如下面这实现类就是我在项目中使用的,用userId字段对8取模得到表的下标值。

public class RemainderStrategy implements Strategy {
   

    /**
     * 取模基数
     */
    private static final int DIVIDER = 8;


    @Override
    public String convert(String sql, Map<String, Object> params) throws Exception {
   
        MySqlParserFactory sqlParserFactory = new MySqlParserFactory();
        Integer reminder = this.getIndex(params);
        return sqlParserFactory.parser(sql, reminder);
    }

    @Override
    public Integer getTableIndex(Map<String, Object> params) throws Exception {
   
        Integer reminder = this.getIndex(params);
        return reminder;
    }

    private Integer getIndex(Map<String, Object> params) throws IllegalAccessException
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值