完美的 jpa 多表 原生sql 分頁查詢

多表分頁查詢,強烈推薦原生sql

一般需要兩個方法,一個查條數,一個查當前頁數據



    @Query(value = "" +
            "" +
            " select " +
            "a.id," +
            "a.title," +
            "a.article_abstract," +
            "a.author_id," +
            "a.like_count ," +
            "a.read_count," +
            "a.tags," +
            "a.create_time," +
            "a.update_time," +
            "a.type," +
            "a.`status` " +
            " from re_article_category rac " +
            "" +
            " left join  " +
            " article a " +
            "" +
            " on a.id=rac.article_id " +
            "" +
            " where rac.category_id= :catId" +
            " and a.status = :status limit :start,:size",nativeQuery = true)
    List<Object[]> pageByCatId(@Param("catId") Integer catId,@Param("status")String status,@Param("start")long start, @Param("size")int size);

   @Query(value = "select" +
           " count(a.id)" +
           " from re_article_category rac" +
           "" +
           " left join " +
           " article a" +
           "" +
           " on a.id=rac.article_id" +
           "" +
           " where rac.category_id= :catId" +
           " and a.status= :status",nativeQuery = true)
    Integer countByCat(@Param("catId") Integer catId,@Param("status") String status);

service 層轉換:

    //根據分類獲取所有文章
    @Override
    public Result getPageByCatId(Integer catId, Integer limit, Integer pageNo) {

  PageRequest pageRequest = PageRequest.of(pageNo, limit);//藉助計算起始位置
        int total=blogDao.countByCat(catId,BLOG_STATUS_NORMAL);// 計算數據總條數
        List<Object[]> records=blogDao.pageByCatId(catId,BLOG_STATUS_NORMAL,pageRequest.getOffset(),pageRequest.getPageSize());// 獲取分頁數據
        Page<Object[]> page =new Page<>(records,limit,pageNo,total);
           page.transferFromSqlList(BlogModel.class);// 轉換分頁數據到具體的java bean
        return Result.success(page);


    }
}

Page.java(自定義工具)


package com.blog.demo.common.util;

import com.google.common.collect.Lists;
import org.springframework.data.domain.PageImpl;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 與具體ORM實現無關的分頁參數及查詢結果封裝.
 *  
 * 
 * @param <T> Page中記錄的類型.
 * 
* @author eagler006 email:[email protected]
* @version  1.2
 */
public class Page<T> {


	//-- 分頁參數 --//
	protected int pageNo = 1;
	protected int pageSize = 15;
	protected int first =-1; //此處添加主要是爲了方便分庫分表時計算各表步進取值,當大於0時說明getFirst()函數不從pageNo計算獲得
	protected boolean autoCount = true;
	protected String sort="id";
	protected String dir= "ASC";
	//-- 返回結果 --//
	protected List result = Lists.newArrayList();
	protected long totalCount = -1;

	//-- 構造函數 --//
	public Page() {
	}
   public Page(List<Object[]> data,int size,int pageNo,int totalCount){
		setPageNo(pageNo);
		setPageSize(size);
		setTotalCount(totalCount);
		setResult(data);

   }
	public Page(int pageSize) {
		this.pageSize = pageSize;
	}

	public void transferFromSqlList(Class clazz){
		List tResult = Lists.newArrayList();
		ArrayList<Object> objArr;
		for (Object objItem : result){
			try {
				objArr = new ArrayList<Object>(Arrays.asList((Object[]) objItem));
				Constructor<T> constructor = clazz.getDeclaredConstructor(objArr.getClass());
				tResult.add(constructor.newInstance(objArr));
			} catch (Exception e){
				e.printStackTrace();
			}
		}
		this.result = tResult;
	}

	public void copyPropertiesFromAnother(Page<?> page){
		this.pageNo = page.getPageNo();
		this.pageSize = page.getPageSize();
		this.first = page.getFirst();
		this.autoCount = page.isAutoCount();
		this.sort = page.getSort();
		this.dir = page.getDir();
		this.totalCount = page.getTotalCount();
	}

	//-- 訪問查詢參數函數 --//
	/**
	 * 獲得當前頁的頁號,序號從1開始,默認爲1.
	 */
	public int getPageNo() {
		return pageNo;
	}

	/**
	 * 設置當前頁的頁號,序號從1開始,低於1時自動調整爲1.
	 */
	public void setPageNo(final int pageNo) {
		this.pageNo = pageNo;

		if (pageNo < 1) {
			this.pageNo = 1;
		}
	}

	public Page<T> pageNo(final int thePageNo) {
		setPageNo(thePageNo);
		return this;
	}

	/**
	 * 獲得每頁的記錄數量,默認爲1.
	 */
	public int getPageSize() {
		return pageSize;
	}

	/**
	 * 設置每頁的記錄數量,低於1時自動調整爲1.
	 */
	public void setPageSize(final int pageSize) {
		this.pageSize = pageSize;

		if (pageSize < 1) {
			this.pageSize = 1;
		}
	}

	public Page<T> pageSize(final int thePageSize) {
		setPageSize(thePageSize);
		return this;
	}

	
	
	/**
	 * @return the sort
	 */
	public String getSort() {
		return sort;
	}

	/**
	 * @param sort the sort to set
	 */
	public void setSort(String sort) {
		this.sort = sort;
	}

	/**
	 * @return the dir
	 */
	public String getDir() {
		return dir;
	}

	/**
	 * @param dir the dir to set
	 */
	public void setDir(String dir) {
		this.dir = dir;
	}

	/**
	 * 根據pageNo和pageSize計算當前頁第一條記錄在總結果集中的位置,序號從1開始.
	 */
	public int getFirst() {
		if(this.first>0)
			return first;
		return ((pageNo - 1) * pageSize) + 1;
	}

	

	/**
	 * @param first the first to set
	 */
	public void setFirst(int first) {
		this.first = first;
	}

	/**
	 * 查詢對象時是否自動另外執行count查詢獲取總記錄數, 默認爲false.
	 */
	public boolean isAutoCount() {
		return autoCount;
	}

	/**
	 * 查詢對象時是否自動另外執行count查詢獲取總記錄數.
	 */
	public void setAutoCount(final boolean autoCount) {
		this.autoCount = autoCount;
	}

	public Page<T> autoCount(final boolean theAutoCount) {
		setAutoCount(theAutoCount);
		return this;
	}

	//-- 訪問查詢結果函數 --//

	/**
	 * 取得頁內的記錄列表.
	 */
	public List getResult() {
		return result;
	}

	/**
	 * 設置頁內的記錄列表.
	 */
	public void setResult(final List result) {
		this.result = result;
	}

	/**
	 * 取得總記錄數, 默認值爲-1.
	 */
	public long getTotalCount() {
		return totalCount;
	}

	/**
	 * 設置總記錄數.
	 */
	public void setTotalCount(final long totalCount) {
		this.totalCount = totalCount;
	}

	/**
	 * 根據pageSize與totalCount計算總頁數, 默認值爲-1.
	 */
	public long getTotalPages() {
		if (totalCount < 0) {
			return -1;
		}

		long count = totalCount / pageSize;
		if (totalCount % pageSize > 0) {
			count++;
		}
		return count;
	}

	/**
	 * 是否還有下一頁.
	 */
	public boolean isHasNext() {
		return (pageNo + 1 <= getTotalPages());
	}

	/**
	 * 取得下頁的頁號, 序號從1開始.
	 * 當前頁爲尾頁時仍返回尾頁序號.
	 */
	public int getNextPage() {
		if (isHasNext()) {
			return pageNo + 1;
		} else {
			return pageNo;
		}
	}

	/**
	 * 是否還有上一頁.
	 */
	public boolean isHasPre() {
		return (pageNo - 1 >= 1);
	}

	/**
	 * 取得上頁的頁號, 序號從1開始.
	 * 當前頁爲首頁時返回首頁序號.
	 */
	public int getPrePage() {
		if (isHasPre()) {
			return pageNo - 1;
		} else {
			return pageNo;
		}
	}
}

效果:

{
  "code": 0,
  "msg": "success",
  "data": {
    "pageNo": 1,
    "pageSize": 10,
    "first": 1,
    "autoCount": true,
    "sort": "id",
    "dir": "ASC",
    "result": [
      {
        "id": 73,
        "title": "標題",
        "content": null,
        "articleAbstract": "這是簡介,請勿驚訝😨",
        "tags": "string",
        "type": "1",
        "readCount": null,
        "likeCount": 1,
        "status": "0",
        "createTime": "2019-06-06T04:32:01.000+0000",
        "updateTime": "2019-06-06T04:32:01.000+0000",
        "categoryId": null
      },
      {
        "id": 107,
        "title": "正式文章",
        "content": null,
        "articleAbstract": "發佈一篇文章",
        "tags": "string",
        "type": "0",
        "readCount": 0,
        "likeCount": 1,
        "status": "0",
        "createTime": "2019-06-06T10:32:11.000+0000",
        "updateTime": "2019-06-06T10:32:11.000+0000",
        "categoryId": null
      }
    ],
    "totalCount": 2,
    "prePage": 1,
    "hasNext": false,
    "nextPage": 1,
    "hasPre": false,
    "totalPages": 1
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章