两种实现方式mycat多租户,枚举分片,注解拦截

 

第一种:注解拦截

  优点:支持进一步分片

缺点:架构配置繁琐

注解式   / *!mycat:schema = [schemaName] * /

/ *!mycat:schema = USER1 * / select * from order;   //模式是逻辑库

可以在每个sql语句前面添加此注解,指定操作的数据库,Mybatis可以重写MappedStatement的  getBoundSql  来添加。

 

第二种:枚举分片

  优点:schema.xml中中配置相对简洁

缺点:不可进一步分片

 

我目前的需求是:按门店分库,按月份分表,需要进行2次划分,因此采用的是第一种方式:注解拦截。此外,公司有100多家门店,因此需要100多个库,在进行分表时,按月份分表会产生12个子表,若每个子表在一个库内,即一个店需要12个库,总共需要1200多个库,所以,考虑再三,采用单库分表的方式,即拆分的子表在一个库内,数据库数量大大减少。

1)在schema.xml中,配置多个schema logic87,一个逻辑库代表一家门店,与一个实际的数据库相对应。

注意:table标签中datanode节点只能写一个,因为是单库分表,subTables中填写的是拆分的12张子表的名字,i_billdel1,.....,i_billdel12,简写i_billdel $ 1-12

     2)修改rule.xml

列是用来分表的字段

dataFormat需要注意,若格式为yyyy-MM-dd或yyyy-MM-dd hh:mm:ss,那么所分的表只能存放自sBeginDate开始一年内的数据,只写MM,则对应表内存放相应月份的数据,即每年1月份的数据都存在1月的表内。

     3)修改的server.xml的中

 

在模式中写上的模式,根用户即可操作逻辑库

     4)在实际数据库中建好这12张子表

      5)连接mycat

mycat的连接端口为8066

连接成功后显示的逻辑库:

6)使用mycat注解

 

 Data_node节点对应实际数据库,这里将将dn3对应的是8M,所以可以通过注解的方式操作逻辑库,mycat会对注解进行解析,找到要查询的数据库。并且可以使用分表字段指定查询的表。

 

我们只需在后台根据用户的信息动态绑定要操作的逻辑库即可。

MyBatis的的可以重写MappedStatement的  getBoundSql  来添加注解

我这里是通过拦截器的方式对SQL添加注解(或叫注释)。

      在MyBatis的配置文件中加入如下代码:

<插件>

<plugin interceptor =“com.htxx.interceptor.MybatisInterceptor”>

<property name =“name”value =“test”> </ property>

</插件>

</插件>

新建一个拦截器

package com.htxx.interceptor;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.Properties;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

// obstioned StatementHandler类中参数类型为Statement的准备方法
//即被截止语句准备(连接var1,整数var2)方法@Incecepts(
{
@ Signature(type = StatementHandler.class,method =“prepare”,args = { Connection .class,Integer.class})})
公共类MybatisInterceptor实现Interceptor {

    @Override
    public Object intercept(Invocation invocation)抛出Throwable {

        StatementHandler statementHandler =(StatementHandler)invocation.getTarget();
        //通过MetaObject优雅访问对象的属性,这里是访问语句处理程序的属性;:MetaObject是Mybatis提供的一个用于方便,
        //优雅访问对象属性的对象,通过它可以简化代码,不需要试试/捕捉各种反映异常,同时它支持对JavaBean,Collection,Map
        三种类型对象的操作.MetaObject metaObject = MetaObject.forObject(statementHandler,SystemMetaObject.DEFAULT_OBJECT_FACTORY,
                SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,new DefaultReflectorFactory());
        //先拦截到RoutingStatementHandler,里面有个StatementHandler类型的委托变量,其实现类是BaseStatementHandler,然后就到到BaseStatementHandler的成员变量mappedStatement
        MappedStatement mappedStatement =(MappedStatement)metaObject.getValue(“delegate.mappedStatement”);
        // id为执行的mapper方法的全路径名,如com.uv.dao.UserMapper.insertUser
        String id = mappedStatement.getId();
        System.out.println(“执行方法的全路径:”+ id);
        // sql语句类型select,delete,insert,update
        String sqlCommandType = mappedStatement.getSqlCommandType()。toString();
        System.out.println(“执行方法的类型:”+ sqlCommandType);
        //数据库连接信息
//配置配置= mappedStatement.getConfiguration();
// ComboPooledDataSource dataSource =(ComboPooledDataSource)configuration.getEnvironment()。getDataSource();
// dataSource.getJdbcUrl();

        BoundSql boundSql = statementHandler.getBoundSql();
        //获取到原始sql语句
        String sql = boundSql.getSql();

       //获取在mapper接口中定义的方法里的参数
        String param = boundSql.getParameterObject()。toString();
        //System.out.println(param);

//在这里实现自己的逻辑,可以对SQL进行拼接
       

        SQL =“/ * mycat:schema = main * /”+ SQL;       

//这样所有的sql语句都会拼接上/ *!mycat:schema = main * /,可以判断原始的sql中否包含某写特殊字符来决定是否添加mycat注释
        //通过反射修改sql语句
        Field field = boundSql ..getClass()getDeclaredField(“SQL”);
        field.setAccessible(真);
        field.set(boundSql,SQL);

        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target){
        return Plugin.wrap(target,this);
    }

    @Override
    public void setProperties(Properties properties){
        //此处可以接收到配置文件的属性参数
        System.out.println(properties.getProperty(“name”));
    }

}
 

 

第二种: 枚举分片

schema.xml 配置如下:   i_billdel所有库中都有, t_user相当于全局表, 放在默认节点中

rule.xml: 

 

即可实现枚举分片,下面查看路由:

  

查的所有库, 下面带上分库字段QYBH:

 

参考:HTTP://www.cnblogs.com/huaxingtianxia/p/7339574.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值