mybatis拦截器分表

时间:2022-06-13
本文章向大家介绍mybatis拦截器分表,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

mybatis提供了拦截器插件用来处理被拦截的方法的某些逻辑.下面会通过创建8张表,当用户注册时,根据对手机号取余入不同的表.

建表

引入插件

<property name="plugins">
    <array>
        <bean id="sharingInterceptor" class="com.lios.base.sharetable.SharingInterceptor"/>
    </array>
</property>

拦截器

具体代码:

/**
 * @author LiosWong
 * @description
 * @date 2018/7/31 下午7:05
 */
@Intercepts(@Signature(type = StatementHandler.class,method = "prepare",args = {Connection.class,Integer.class}))
public class SharingInterceptor implements Interceptor{
    Logger logger = LoggerFactory.getLogger(SharingInterceptor.class);
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
        MetaObject metaObject = MetaObject.forObject(statementHandler,SystemMetaObject.DEFAULT_OBJECT_FACTORY,SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,reflectorFactory);
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        String id = mappedStatement.getId();
        id = id.substring(0,id.lastIndexOf("."));
        Class cls = Class.forName(id);
        SegmentTable segmentTable = (SegmentTable) cls.getAnnotation(SegmentTable.class);
        if(segmentTable!=null){
            String sql = (String) metaObject.getValue("delegate.boundSql.sql");
            BoundSql boundSql = statementHandler.getBoundSql();
            String tableKey = StrategyFactory.createShareStrategy(segmentTable.shareType()).setSegmentTable(segmentTable).setBoundSql(boundSql).getRouteValue();
            metaObject.setValue("delegate.boundSql.sql",sql.replaceFirst(segmentTable.tableName(),segmentTable.tableName()+tableKey));
        }
        return invocation.proceed();
    }
    @Override
    public Object plugin(Object target) {
        if(target instanceof StatementHandler){
            return Plugin.wrap(target,this);
        }
        return target;
    }
    @Override
    public void setProperties(Properties properties) {

    }
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SegmentTable {
    /**
     * 表名称
     * @return
     */
    String tableName()  default "";


    /**
     * 分表策略
     * @return
     */
    ShareType shareType() default ShareType.MOD;


    /**
     * 分表数量
     * @return
     */
    int tableNum() default 0;

    /**
     * 分表数量
     * @return
     */
    String shareBy() default "";
}
@Repository
@DataSource(value = DynamicDataSourceGlobal.LOCAL)
@SegmentTable(tableName = "user",shareType = ShareType.MOD,tableNum = 8,shareBy = "mobile")
public class UserInfoDaoImpl extends AbstractBaseMapper<UserInfoEntity> implements UserInfoDao{
    @Override
    public UserInfoEntity selectById(Long id) {
        return this.getSqlSession().selectOne(this.getStatement(".selectById"),id);
    }
    @Override
    public UserInfoEntity selectByMobile(String mobile) {
        return this.getSqlSession().selectOne(this.getStatement(".selectByMobile"),mobile);
    }
    @Override
    public UserInfoEntity insert(UserInfoEntity userInfoEntity){
        this.getSqlSession().insert(this.getStatement(".insert"),userInfoEntity);
        return null;
    }
}

StrategyFactory根据不同分表策略处理相应的逻辑,拦截器里主要思路就是拦截需要处理的方法,然后对拦截参数、拦截结果集处理,然后重新构建sql语句并执行.

数据录入