天天看點

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