主题:不写Order by,会自动生成,导致md文件里的order by重复

andnnl 2019年05月13日 186

数据库SQL Server 2012

调用 代码

SmsMobiles sm=new SmsMobiles();
sm.setUcuid("xxxx");
sm.setMinSendTime(new SimpleDateFormat("yyyy-MM-dd").parse("2019-05-01"));
PageQuery pageQuery = new PageQuery();
pageQuery.setParas(sm);
pageQuery.setOrderBy(null);
sqlManager.pageQuery("smsMobiles.sample", SmsMobiles.class,pageQuery);
System.out.println(pageQuery.getTotalPage());
System.out.println(pageQuery.getTotalRow());
System.out.println(pageQuery.getPageNumber());
List<SmsMobiles> list2 = pageQuery.getList();
System.out.println(JsonLib.toJson(list2));


md文件

sample
===
* 注释


	select 
	@pageTag(){
	    #use("cols")# 
	@}
	from TBL_SMS_MOBILES  where  #use("condition")#
	@pageIgnoreTag(){
	    order by SENDTIME desc
	@}

cols
===
	ID,UCUID,MOBILE,SENDTIME


condition
===

	1 = 1  
	@if(!isEmpty(ucuid)){
	 and ucuid=#ucuid#
	@}
	@if(!isEmpty(mobile)){
	 and MOBILE=#mobile#
	@}
	
	@if(!isEmpty(sendtime)){
	 and SENDTIME=#sendtime#
	@}
	@if(!isEmpty(minSendTime)){
     and SENDTIME>=#minSendTime#
    @}
    @if(!isEmpty(maxSendTime)){
     and SENDTIME<#maxSendTime#
    @}
	
	
	
	


生成的SQL,多了order by current_timestamp,数据库都没这个字段

┏━━━━━ Debug [smsMobiles.sample] ━━━
┣ SQL:	  select count(1) from TBL_SMS_MOBILES where 1 = 1 and SENDTIME>=? and UCUID=? 
┣ 参数:	 [2019-05-01 00:00:00.000, xxxx]
┣ 位置:	 com.jiaying.GeneratorMain.testSmsSelect(GeneratorMain.java:77)
┣ 时间:	 239ms
┣ 结果:	 [1]
┗━━━━━ Debug [smsMobiles.sample] ━━━


┏━━━━━ Debug [smsMobiles.sample_page] ━━━
┣ SQL:	  select ID,UCUID,MOBILE,SENDTIME from TBL_SMS_MOBILES where 1 = 1 and SENDTIME>=? and UCUID=? order by SENDTIME desc order by current_timestamp offset ? rows fetch next ? rows only 
┣ 参数:	 [2019-05-01 00:00:00.000, xxxx, 0, 20]
┣ 位置:	 com.jiaying.GeneratorMain.testSmsSelect(GeneratorMain.java:77)
┗━━━━━ Debug [ ERROR:关键字 'order' 附近有语法错误。] ━━━

andnnl 2019年05月13日

Spring Boot工程

<dependency>
	<groupId>com.ibeetl</groupId>
	<artifactId>beetl-framework-starter</artifactId>
	<version>1.1.81.RELEASE</version>
</dependency>
andnnl 2019年05月13日

image.png

加了this.getOrderBy(),导致匹配不上

andnnl 2019年06月03日

自己写个

    @Override
    public String getPageSQL(String sql) {
        StringBuilder builder = new StringBuilder(sql).append(this.getOrderBy());
        //sqlserver 2012 以上的 offset 分页必须要跟在order by后面,因此如果语句本身没有order by则为其添加一个按默认时间戳的order by
//        if (!builder.toString().matches("(?i).* order by[^)]+$")) {
        if (!builder.toString().matches("(?ism).* order +?by[^)]+.*' order by '\\+_orderBy\\)# $")) {
            builder.append(" order by current_timestamp");
        }
        return builder.append(" offset ")
                .append(HOLDER_START).append(OFFSET).append(HOLDER_END)
                .append(" rows fetch next ")
                .append(HOLDER_START).append(PAGE_SIZE).append(HOLDER_END)
                .append(" rows only ").toString();
    }
darren 2019年06月03日

之前写的确实有些bug:

  • 没有考虑多行正则匹配(SQL允许换行)
  • order和by之间的空格可能有多行的情况
  • 没有考虑beetl内置函数的情况

针对上述的三个问题,做了一下修复,应该能兼容你遇到的问题


    @Override
    protected String getOrderBy() {
        //重写getOrderBy,如果设置了分页的order by条件 则按 order by 否则添加一个 current_timestamp 来排序
        return lineSeparator + HOLDER_START + "text(' order by ' + _orderBy!'current_timestamp')" + HOLDER_END + " ";
    }

    @Override
    public String getPageSQL(String sql) {
        StringBuilder builder = new StringBuilder(sql);
        //sqlserver 2012 以上的 offset 分页必须要跟在order by后面
        //因此如果语句本身没有order by则为其添加一个按默认时间戳的order by
        //先判断 是否有包含order by条件的 pageIgnoreTag函数 或者单纯的order by xxx结尾
        //有则忽略不再拼接条件,没有则拼接一个定制的getOrderBy函数
        if(!sql.matches("(?is).*pageIgnoreTag\\s*\\(\\s*\\)[^}]*?order\\s+by.*|.*\\s+order\\s+by[^)]+$")) {
            builder.append(this.getOrderBy());
        }
        return builder.append(" offset ")
        .append(HOLDER_START).append(OFFSET).append(HOLDER_END)
        .append(" rows fetch next ")
        .append(HOLDER_START).append(PAGE_SIZE).append(HOLDER_END)
        .append(" rows only ").toString();
    }