MyBatisPlus解决SQLServer分页问题

0

最近有个项目需要迁移SQLServer,原来使用的MySQL,发现有些SQL有些问题,特别是分页统计条数。

原来使用MySQL时子查询里面可以含有order by,但是SQLServer不行,提示:

org.springframework.jdbc.UncategorizedSQLException: 
	### Error querying database.  Cause: com.microsoft.sqlserver.jdbc.SQLServerException: The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.

其实默认MyBatisPlus是解决了这个问题的,简单语句会去掉排序,复杂语句通过TOP 100 PERCENT解决了,但是还是存在部分有问题。

如果语句之中别名存在关键字时就会导致解析不了SQL,最好的解决方法就是修改别名。
也可以通过将排序字段设置到Page对象里面解决,如果设置到wrapper里面也是不行的。
或者通过自定义统计语句pageQuery.setCountId(null);

这里还有一个BUG,就是如果语句里面使用了PARTITION BY和排序的时候SQLServer2005Dialect这个解析是存在问题的,如下代码:

    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;
        }
    } 

这个就会导致排序字段截取错误,建议改为:

	private String getOrderByPart(String sql) {
		final String loweredString = sql.toLowerCase();
		final int partitionByIndex = loweredString.lastIndexOf("partition by");
		final int orderByIndex = loweredString.indexOf("order by", partitionByIndex);
		final int lastOrderByIndex = loweredString.lastIndexOf("order by");
		if (partitionByIndex >= 0 && orderByIndex != lastOrderByIndex) {
			return sql.substring(lastOrderByIndex);
		} else if(lastOrderByIndex >= 0) {
			return sql.substring(lastOrderByIndex);
		}
		return StringPool.EMPTY;
	}

这里需要用到反射强制替换对象:

	final Field register = DialectFactory.class.getDeclaredField("DIALECT_REGISTRY");
	register.setAccessible(true);
	final Object object = register.get(DialectFactory.class);
	final Field enumMap = DialectRegistry.class.getDeclaredField("dialect_enum_map");
	enumMap.setAccessible(true);
	final Map<DbType, IDialect> map = (Map<DbType, IDialect>) enumMap.get(object);

最后说个取巧的方式,就是其实这里可以在order by中间加个空格就可以解决了,其实最开始的时候我也想到了替换order by,但是想了半天就是没想到在中间加空格,所以有时候人在时候反而更加清醒。