【原创】Mybaties二级缓存,分页,多租户三合一插件

简介

  1. 本案例解决了为全网最强mybaties二级缓存解决方案,搞过mybaties二级缓存的朋友应该知道,mybaties自带的二级缓存只会对对同一个namespace下的生效,例如A
    namespace下对一个表执行了delete,update,insert任何一个操作修改了表数据之后,B namespace
    select该表的sql的缓存并不会清除,只会把A
    namespace下对应的select该表的查询清除,从而造成脏读现象,本案例重新实现了mybaties二级缓存的逻辑,完全解决脏读问题。

properties.setProperty(“opencache”, “1”);//是否开启缓存1开始,2关闭

  1. 本案例实现了,mybaties拦截器进行分页的操作,用户只需要定义一个page类,拦截器可进行自动拦截之后分页

例如 Page page = new Page(1, 3);

  1. 本案例实现了多租户的功能,仅需在插件里配置多租户的字段和值,即可实现多租户功能,用户开发过程中,就不需要关注多租户字段了例如

properties.setProperty(“tenantId”, “tenant_id”);//租户字段
properties.setProperty(“tenantValue”, “1”);//租户值

以下为代码,如有问题,请留言指出。

注册插件

/**
 * 功能描述:注册插件
 *
 * @author chenyan
 * @date 2019/6/4 10:54
 */
@EnableTransactionManagement
@Configuration
@MapperScan({"com.hyit.system.demo.dao"})
public class MapperConfig {
//    @Value(value = "${sql.tenantId}")
//    private String tenantId;
//    @Value(value = "${sql.tenantValue}")
//    private String tenantValue;
//    @Value(value = "${sql.opencache}")
//    private String opencache;

    //注册插件
    @Bean
    public PageInterceptor myPlugin() {
        PageInterceptor myPlugin = new PageInterceptor();
        //设置参数,比如阈值等,可以在配置文件中配置
        Properties properties = new Properties();
        properties.setProperty("opencache", "1");//是否开启缓存1开始,2关闭
        properties.setProperty("tenantId", "tenant_id");//租户字段
        properties.setProperty("tenantValue", "1");//租户值
        myPlugin.setProperties(properties);
        return myPlugin;
    }
}

分页拦截器

/**
 * 功能描述:mybaties分页拦截器,实现二级缓存跨namespace存取
 * , Connection.class
 *
 * @author chenyan
 * @date 2019/6/4 10:54
 */

@Intercepts({
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
})
public class PageInterceptor implements Interceptor {

    public static final Logger logger = LoggerFactory.getLogger(PageInterceptor.class);

    private RedisTemplate<String, Object> redisTemplate = SpringContextHolder.getBean("redisTemplate");
    //开启二级缓存
    private String opencache;
    //多租户id
    private String tenantId;
    //多租户id
    private String t;
    //多租户值
    private String tenantValue;


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        doInvocation(invocation);
        return invocation.proceed();
    }

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

    //    在配置插件的时候配置默认参数
    @Override
    public void setProperties(Properties properties) {
        String opencache = properties.getProperty("opencache");
        String tenantId = properties.getProperty("tenantId");
        String tenantValue = properties.getProperty("tenantValue");
        this.opencache = opencache;
        this.tenantId = tenantId;
        this.tenantValue = tenantValue;
    }

    //基于mycat方式
    private Object mycatInvocation(Invocation invocation) throws Throwable {
        long stime = System.currentTimeMillis();
        StatementHandler statementHandler = getActuralHandlerObject(invocation);
        MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
        String sql = statementHandler.getBoundSql().getSql();

        //二级缓存方案
        if ("1".equals(this.opencache)) {
            if (checkSql(sql)) {
                try {
                    Set<TableStat.Name> nameSet = sqlParser(sql);
                    nameSet.stream().forEach(t -> {
                        Set<String> keys = redisTemplate.keys("*:*" + t + "*");
                        if (!CollectionUtils.isEmpty(keys)) {
                            redisTemplate.delete(keys);
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        // 检测通过,是select语句
        if (checkIsSelectFalg(sql)) {
            //分页方案
            BoundSql boundSql = statementHandler.getBoundSql();
            Object paramObject = boundSql.getParameterObject();
            Page pageParam = getPageParam(paramObject);
            if (pageParam == null) {
                Object o = invocation.proceed();
                long etime = System.currentTimeMillis();
                logger.info((etime - stime) + "");
                return o;
            } else {
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值