mybaits plus+mycat+sql server 2008 分页的一些坑,做记录

首先 mycat2 不支持 sql server

所以用mycat1吧,真是血和泪的教训

正常整合mybaits plus+mycat+sql server2008 是没有问题的,但当需要用到Mycat注解时就会有问题

1、mybaits plus 是依据连接的url 来判断数据库方言的,当使用mycat 的时,mybaits plus会使用mysql 的数据方言,mycat 收到mybaits plus的SQL 会依据连接的数据库自动转换成相关的数据库方言,到分库分表上的数据库执行,这里一切是正常的

2、当必须使用mycat 注解时,mycat 就不会对收到 的SQL 做处理,只是在确认分片信息后就会把SQL发到相关的数据库上执行,那就会有一个坑,只是对sql server2008的分页来说。

这里 mybaits plus 发的SQL 是mysql类型的,mycat 只直把sql 发给sql server数据库执行,就会报错,那么把mybaits plus 的数据库方言改为sql server 2015 ,这时,mybaits plus对sql server 2015 的分页 IDialect 简单来说就是识别select ,然后加上

WITH selectTemp AS (SELECT " + distinctStr + "TOP 100 PERCENT " +
        " ROW_NUMBER() OVER (" + orderby + ") as __row_number__, " + sqlBuilder +
        ") SELECT * FROM selectTemp WHERE __row_number__ BETWEEN " 

等这些,但是我们使用了mycat注解 ,识别就会报错。会生成错误的SQL 语句,(具体是在注解前加上分页的语句,mycat 无法识别,报错)

解决的办法:

1、手写分页,不使用mybaits plus的分页。具体实现请参照其它文章

2、修改mybaits plus 的拦截器,重写sql server 2015的IDialect

public class MycatSqlserverDialect implements IDialect {


    private static String getOrderByPart(String sql) {
        //将字符串中的所有大写字母转换为小写字母
        String loweredString = sql.toLowerCase();
        int orderByIndex = loweredString.indexOf("order by");
        if (orderByIndex != -1) {
            return sql.substring(orderByIndex);
        } else {
            return StringPool.EMPTY;
        }
    }

    @Override
    public DialectModel buildPaginationSql(String originalSql, long offset, long limit) {
        StringBuilder pagingBuilder = new StringBuilder();
        String orderby = getOrderByPart(originalSql);
        String distinctStr = StringPool.EMPTY;


        String loweredString = originalSql.toLowerCase();
        String sqlPartString = originalSql;
        if (loweredString.trim().startsWith("select")) {
            int index = 6;
            if (loweredString.startsWith("select distinct")) {
                distinctStr = "DISTINCT ";
                index = 15;
            }
            sqlPartString = sqlPartString.substring(index);
        }
        //识别mycat 的注解
        else if(loweredString.trim().startsWith("/* !mycat:")){
            int index=6;
            if (loweredString.contains("select distinct")) {
                distinctStr = "DISTINCT ";
                 index = 15;
            }
            //截取mycat 注解和 sql 语句
            int i = sqlPartString.indexOf("/", 1);
            String mycatSql = sqlPartString.substring(0, i+1);
            String sql = sqlPartString.substring(i + 1);
            int s = sql.indexOf("s");
            sql = sql.substring(s+index);
            StringBuilder mycatBuilder = new StringBuilder();
            mycatBuilder.append(mycatSql);
            StringBuilder sqlBuilder = new StringBuilder();
            sqlBuilder.append(sql);
            if (StringUtils.isEmpty(orderby)) {
                orderby = "ORDER BY CURRENT_TIMESTAMP";
            }
            long firstParam = offset + 1;
            long secondParam = offset + limit;
            //把mycat注解放到sql 语句前面 指定数据库进行查询
            String MycatSql = mycatBuilder+"WITH selectTemp AS (SELECT " + distinctStr + "TOP 100 PERCENT " +
                    " ROW_NUMBER() OVER (" + orderby + ") as __row_number__, " + sqlBuilder +
                    ") SELECT * FROM selectTemp WHERE __row_number__ BETWEEN " +
                    //FIX#299:原因:mysql中limit 10(offset,size) 是从第10开始(不包含10),;而这里用的BETWEEN是两边都包含,所以改为offset+1
                    firstParam + " AND " + secondParam + " ORDER BY __row_number__";
            return new DialectModel(MycatSql, firstParam, secondParam);

        }
        pagingBuilder.append(sqlPartString);

        // if no ORDER BY is specified use fake ORDER BY field to avoid errors
        if (StringUtils.isEmpty(orderby)) {
            orderby = "ORDER BY CURRENT_TIMESTAMP";
        }
        long firstParam = offset + 1;
        long secondParam = offset + limit;
        String sql = "WITH selectTemp AS (SELECT " + distinctStr + "TOP 100 PERCENT " +
                " ROW_NUMBER() OVER (" + orderby + ") as __row_number__, " + pagingBuilder +
                ") SELECT * FROM selectTemp WHERE __row_number__ BETWEEN " +
                //FIX#299:原因:mysql中limit 10(offset,size) 是从第10开始(不包含10),;而这里用的BETWEEN是两边都包含,所以改为offset+1
                firstParam + " AND " + secondParam + " ORDER BY __row_number__";
        return new DialectModel(sql, firstParam, secondParam);
    }

}

在分页插件里加上自己写的IDialect


/**
 * mybatis-plus配置
 *
 * @author Mark sunlightcs@gmail.com
 */
@Configuration
public class MybatisPlusConfig {



  /**
   * 分页插件
   */
  @Bean
  public PaginationInterceptor paginationInterceptor() {
    PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
    //paginationInterceptor.setDialectType("sqlserver2005");
    paginationInterceptor.setDialectClazz("com.manage.modules.order.util.config.MycatSqlserverDialect");
    return paginationInterceptor;
  }

  @Bean
  public ISqlInjector sqlInjector() {
    return new LogicSqlInjector();
  }

这里注意,当使用方法2时,所有mybaits plus 发送的SQL 都会是sql server,这里需要权衡一下,

唉, 我也不知道,为什么需要用mycat 注解,权衡一下,其实是可以不用的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值