天天看點

Java實作分頁功能常見的幾種方法

作者:老周聊架構
歡迎大家關注我的公衆号【老周聊架構】,Java後端主流技術棧的原理、源碼分析、架構以及各種網際網路高并發、高性能、高可用的解決方案。

一、limit關鍵字

service層

@Service
@Transactional
public class ImplStudentService implements StudentService {

@Resource
private  StudentDao  studentDao;

    @Override
    public List<Student>  selectAllStudent(String province, Integer offset, Integer limit) {
        return studentDao.selectAll(province,offset,limit);
    }
}
           

sql語句

select * from student where province = #{province}  limit #{offset},#{limit}
           

二、hibernate分頁

service層

@Override
  public List getStudents(Integer  pageNo,Integer  pageSize) throws Exception {
  // 分頁資料
  int[] startIdAndCount = new int[2];
  startIdAndCount[0] = pageNo * pageSize;
  startIdAndCount[1] = pageSize;
  return studentDao.selectStudentsByPage(startIdAndCount);
 }
           

dao層

@Override
public List findByHqlPage(int[] startIdAndCount) throws Exception {
    String hql = "...";
    try {
        Query query = getSession().createQuery(hql);
        // 設定分頁
        if (startIdAndCount != null && startIdAndCount.length > 0) {
            int rowStartIdx = Math.max(0, startIdAndCount[0]);
            if (rowStartIdx > 0) {
                query.setFirstResult(rowStartIdx);// 設定開始取值的索引
            }
            if (startIdAndCount.length > 1) {
                int rowCount = Math.max(0, startIdAndCount[1]);
                if (rowCount > 0) {
                query.setMaxResults(rowCount);// 設定結束取值的索引
                }
            }
        }
        return query.list();
    } catch (RuntimeException re) {
        log.error("分頁查詢失敗!", re);
        throw re;
    }
}
           

三、截取List查詢結果分頁(簡單粗暴)

...
List<StudentEnroll> students = studentlDao.getAllStudents();
int count = 0;
if(studentEnrolls != null && studentEnrolls.size() > 0) {
    count = studentEnrolls.size();
    int fromIndex = pageNo * pageSize;
    int toIndex = (pageNo + 1) * pageSize;
    if(toIndex > count) {
        toIndex = count;
    }
    List<StudentEnroll> pageList = studentEnrolls.subList(fromIndex, toIndex);
...
           

四、mybatis架構pageHelper插件分頁

Spring整合:

導入pom.xml

<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
 <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>5.1.2</version>
 </dependency>
           

配置項目配置檔案(我在spring和mybatis整合的配置檔案中配置的,如果在mybatis核心配置檔案中配置,百度一下)

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 依賴資料源 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 注冊加載myBatis映射檔案 -->
        <property name="mapperLocations">
            <array>
                <value>classpath*:com/yyz/mapper/*Mapper.xml</value>
            </array>
        </property>
        <!-- PageHelper分頁配置 -->
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <!--使用下面的方式配置參數,一行配置一個,後面會有所有的參數介紹 -->
                        <value>
                    <!--helperDialect屬性來指定分頁插件使用哪種方言。-->
                            helperDialect=mysql
                    <!--分頁合理化參數,設定為true時,pageNum<=0時會查詢第一頁,pageNum>pages(超過總數時),會查詢最後一頁。-->
                            reasonable=true
                    <!--為了支援startPage(Object params)方法,增加了該參數來配置參數映射,用于從對象中根據屬性名取值,
                        可以配置 pageNum,pageSize,count,pageSizeZero,reasonable-->
                            params=count=countSql
                    <!--支援通過Mapper接口參數來傳遞分頁參數,預設值false,分頁插件會從查詢方法的參數值中,自動根據上面 params 配
                     置的字段中取值,查找到合适的值時就會自動分頁。-->
                            supportMethodsArguments=true
                    <!--預設值為 false。設定為 true 時,允許在運作時根據多資料源自動識别對應方言的分頁-->
                            autoRuntimeDialect=true
                        </value>
                    </property>
                </bean>
            </array>
        </property>
        <!-- 給資料庫實體起别名 -->
        <property name="typeAliasesPackage" value="com.yyz.entity;"/>
 </bean>
           

SpringBoot整合:

<!--分頁插件-->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>最新版本</version>
</dependency>
           

配置項目application.yml檔案

#bybatis分頁插件配置
pagehelper:
  helper-dialect: mysql  #資料庫
  reasonable: true
  support-methods-arguments: true
  params: count=countSql
           

## 标題分頁插件參數:

分頁插件提供了多個可選參數,這些參數使用時,按照上面配置方式中的示例配置即可。

分頁插件可選參數如下:

dialect:預設情況下會使用 PageHelper 方式進行分頁,如果想要實作自己的分頁邏輯,可以實作

Dialect(com.github.pagehelper.Dialect) 接口,然後配置該屬性為實作類的全限定名稱。 使用自定義

dialect 實作時,下面的參數沒有任何作用。

helperDialect:分頁插件會自動檢測目前的資料庫連結,自動選擇合适的分頁方式。

oracle,mysql,mariadb,sqlite,hsqldb,postgresql,db2,sqlserver,informix,h2,sqlserver2012,derby

特别注意:使用 SqlServer2012 資料庫時,需要手動指定為 sqlserver2012,否則會使用 SqlServer2005

的方式進行分頁。

offsetAsPageNum:預設值為 false,該參數對使用 RowBounds 作為分頁參數時有效。 當該參數設定為 true

時,會将 RowBounds 中的 offset 參數當成 pageNum 使用,可以用頁碼和頁面大小兩個參數進行分頁。

rowBoundsWithCount:預設值為false,該參數對使用 RowBounds 作為分頁參數時有效。

當該參數設定為true時,使用 RowBounds 分頁會進行 count 查詢。

pageSizeZero:預設值為 false,當該參數設定為 true 時,如果 pageSize=0 或者

RowBounds.limit = 0 就會查詢出全部的結果(相當于沒有執行分頁查詢,但是傳回結果仍然是 Page 類型)。

reasonable:分頁合理化參數,預設值為false。當該參數設定為 true 時,pageNum<=0 時會查詢第一頁,pageNum>pages(超過總數時),會查詢最後一頁。預設false 時,直接根據參數進行查詢。

params:為了支援startPage(Object params)方法,增加了該參數來配置參數映射,用于從對象中根據屬性名取值,

可以配置 pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用預設值,

預設值為pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero。

supportMethodsArguments:支援通過 Mapper

接口參數來傳遞分頁參數,預設值false,分頁插件會從查詢方法的參數值中,自動根據上面 params

配置的字段中取值,查找到合适的值時就會自動分頁。

aggregateFunctions:預設為所有常見資料庫的聚合函數,允許手動添加聚合函數(影響行數),所有以聚合函數開頭的函數,在進行

count 轉換時,會套一層。其他函數和列會被替換為 count(0),其中count列可以自己配置。

重要提示:

當 offsetAsPageNum=false 的時候,由于 PageNum 問題,RowBounds查詢的時候 reasonable 會強制為 false。使用 PageHelper.startPage 方法不受影響。

service層

@Override
public ResponseResult selectAllStudent(Integer pageNum, Integer pageSize) {
    Map<String,Object> map = new HashMap<>();
    PageHelper.startPage(pageNum,pageSize);
    List<Student>  students = studentMapper.selectAllStudents();
    PageInfo pageInfo = new PageInfo(students);
    long total = pageInfo.getTotal();
    map.put("result",pageInfo);
    map.put("count",total);
    return ResponseResultUtil.success(map);
}
           

詳細請看 SpringBoot內建MyBatis的分頁插件PageHelper

五、springData分頁

service層

...
Sort.Order travelDate = new Sort.Order(Sort.Direction.DESC, "travelDate");
Sort.Order createdTime = new Sort.Order(Sort.Direction.DESC, "createdTime");
Sort sort = new Sort(travelDate, createdTime);
Pageable pageable = new PageRequest(page, pageSize, sort);
List<TravelItem> items = null;
try {
    items = travelRepository.getTravelItemsByTravelDateBetweenAndUserId(theStartDate, theEndDate, openId, pageable);
} catch (Exception e) {
    throw new DatabaseRelatedException("TravelRepository異常");
}
 ...
           

dao層:接口繼承的是PagingAndSortingRepository接口,注意要加@Repository注解

繼續閱讀