天天看点

Mybatis 使用annotation实现动态sql

在开发过程中有很多业务需要动态生成sql才能完成,例如前端展示某物品时就需要对物品进行分页,排序。这就需要需要至少传入四个参数,第几页,页大小,排序字段,升序还是降序。根据这四个参数动态生成sql。mybatis中提供使用xml和annotation的方式管理sql语句。这里介绍使用annotation的方式,因为annotation更多体现面向对象化。

annotation中动态生成sql有如下两种方式。

  1. annotation中拼接sq

    不太推荐这种方式,因为这种方法跟xml差多,需要其他的标签,严重影响代码的可读性。例如实现分页查询的动态sql如下:

@Select({"<script>" ,
            "select name,price,num from bin_info.goods ",
            "<if test='sortField!=null'> order by #{sortField} </if>",
            "<if test='pageNumber!='' and pageSize!='''> limit #{pageNumber} offset #{pageSize} </if>",
            "</script>"})
    List<Goods> findGoods(PageDto dto);
           
  1. annotation中引用provider

    这种方式更对像化,需要引入一个provider类,provider主要完成sql的动态拼接,然后在mapper层通过反射的方式引用相应的sql,实现1中的逻辑如下两步:

    首先,创建用于拼接动态sql的provider:

import com.channing.dto.PageDto;
import org.apache.ibatis.jdbc.SQL;

import java.util.Map;

/**
 * @author :channing
 * @date :Created in 5/12/2020 6:03 PM
 * @description:${The sql provider for goods}
 */
public class GoodsSqlProvider {
    public String findByPage(Map<String,PageDto> param){
        PageDto pageDto = param.get("page_dto");
        String pageString = new SQL(){
            {//notice: here used code block, if don't use,the following sql FUNCTION can not be used.
                SELECT("name,price,num");
                FROM("bin_info.goods");
                String sortField = pageDto.getSortField();
                if(sortField!=null) ORDER_BY(sortField);
                if(pageDto.getPageNumber()!=null && pageDto.getPageSize()!=null) {
                    LIMIT(pageDto.getPageNumber().intValue());
                    OFFSET(pageDto.getPageSize().intValue());
                }
            }
        }.toString();

        return pageString;


    }
}

           

其次,定义mapper中的接口:

@SelectProvider(method = "findByPage",type=GoodsSqlProvider.class)
    List<Goods> findGoods(@Param("page_dto")PageDto dto);
           

本文中使用的PageDto如下,其中使用Long类型是因为可以设为null,当为null时 相应的参数可以不用拼到sql中,如果使用long的话,每次必须进行分页。

import lombok.Data;

/**
 * @author :channing
 * @date :Created in 5/12/2020 5:09 PM
 * @description:${The page Dto contains four 4 parameters, dynamic sql will be based on them.}
 */
@Data
public class PageDto {
    private Long pageNumber;
    private Long pageSize;
    private String sortField;
    private String sortOrder;
}
           

注:本文中使用的是postgresql