欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Mybatis極其(最)簡(好)單(用)的一個(gè)分頁插件

 更新時(shí)間:2016年12月27日 09:35:52   作者:isea533  
這篇文章主要介紹了詳解Mybatis極其(最)簡(好)單(用)的一個(gè)分頁插件,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。

注意:這篇博客已經(jīng)和當(dāng)前的分頁插件完全不一樣了,所以建議大家通過上面項(xiàng)目地址查看最新的源碼和文檔來了解。

以前為Mybatis分頁查詢發(fā)愁過,而且在網(wǎng)上搜過很多相關(guān)的文章,最后一個(gè)都沒采用。在分頁的地方完全都是手寫分頁SQL和count的sql,總之很麻煩。

后來有一段時(shí)間想從Mybatis內(nèi)部寫一個(gè)分頁的實(shí)現(xiàn),我對LanguageDriver寫過一個(gè)實(shí)現(xiàn),自動(dòng)分頁是沒問題了,但是查詢總數(shù)(count)仍然沒法一次性解決,最后不了了之。

最近又要用到分頁,為了方便必須地寫個(gè)通用的分頁類,因此又再次參考網(wǎng)上大多數(shù)的Mybatis分頁代碼。

實(shí)際上在很早之前,有人在github上開源過一個(gè)實(shí)現(xiàn),支持MySQL,Oracle,sqlserver的,和上面這個(gè)參考的比較類似,考慮的更全面。但是我覺得太多類太麻煩了,所以自己實(shí)現(xiàn)了一個(gè)只有一個(gè)攔截器的類,實(shí)際上可以分為兩個(gè)類,其中一個(gè)類被我寫成靜態(tài)類放在了攔截器中,你也可以將Page類提取出來,方便使用Page。

先說實(shí)現(xiàn)方法,該插件只有一個(gè)類:PageHelper.Java

攔截器簽名為:

@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class}), 
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})}) 

這里的簽名對整個(gè)實(shí)現(xiàn)和思想至關(guān)重要,首先我攔截prepare方法來改分頁SQL,來做count查詢。然后我攔截handleResultSets方法來獲取最后的處理結(jié)果,將結(jié)果放到Page對象中。

下面是修改分頁的代碼,是針對Oracle數(shù)據(jù)進(jìn)行的修改,如果有用其他數(shù)據(jù)庫的,自己修改這里的代碼就可以。

/** 
   * 修改原SQL為分頁SQL 
   * @param sql 
   * @param page 
   * @return 
   */ 
  private String buildPageSql(String sql, Page page) { 
    StringBuilder pageSql = new StringBuilder(200); 
    pageSql.append("select * from ( select temp.*, rownum row_id from ( "); 
    pageSql.append(sql); 
    pageSql.append(" ) temp where rownum <= ").append(page.getEndRow()); 
    pageSql.append(") where row_id > ").append(page.getStartRow()); 
    return pageSql.toString(); 
  } 

之后在下面的setPageParameter方法中一個(gè)selelct count語句,這里也需要根據(jù)數(shù)據(jù)庫類型進(jìn)行修改:

// 記錄總記錄數(shù) 
String countSql = "select count(0) from (" + sql + ")"; 

為什么我不提供對各種數(shù)據(jù)庫的支持呢,我覺得沒必要,還有些數(shù)據(jù)庫不支持分頁,而且這個(gè)插件越簡單對使用的開發(fā)人員來說越容易理解,越容易修改。修改成自己需要的分頁查詢肯定不是問題。

最后上完整代碼(繼續(xù)看下去,下面還有使用方法):(點(diǎn)擊下載

package com.mybatis.util; 
import org.apache.ibatis.executor.parameter.ParameterHandler; 
import org.apache.ibatis.executor.resultset.ResultSetHandler; 
import org.apache.ibatis.executor.statement.StatementHandler; 
import org.apache.ibatis.mapping.BoundSql; 
import org.apache.ibatis.mapping.MappedStatement; 
import org.apache.ibatis.plugin.*; 
import org.apache.ibatis.reflection.MetaObject; 
import org.apache.ibatis.reflection.SystemMetaObject; 
import org.apache.ibatis.scripting.defaults.DefaultParameterHandler; 
import org.apache.log4j.Logger; 
 
import java.sql.*; 
import java.util.List; 
import java.util.Properties; 
 
/** 
 * Mybatis - 通用分頁攔截器 
 * @author liuzh/abel533/isea 
 * Created by liuzh on 14-4-15. 
 */ 
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class}), 
    @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})}) 
public class PageHelper implements Interceptor { 
  private static final Logger logger = Logger.getLogger(PageHelper.class); 
 
  public static final ThreadLocal<Page> localPage = new ThreadLocal<Page>(); 
 
  /** 
   * 開始分頁 
   * @param pageNum 
   * @param pageSize 
   */ 
  public static void startPage(int pageNum, int pageSize) { 
    localPage.set(new Page(pageNum, pageSize)); 
  } 
 
  /** 
   * 結(jié)束分頁并返回結(jié)果,該方法必須被調(diào)用,否則localPage會(huì)一直保存下去,直到下一次startPage 
   * @return 
   */ 
  public static Page endPage() { 
    Page page = localPage.get(); 
    localPage.remove(); 
    return page; 
  } 
 
  @Override 
  public Object intercept(Invocation invocation) throws Throwable { 
    if (localPage.get() == null) { 
      return invocation.proceed(); 
    } 
    if (invocation.getTarget() instanceof StatementHandler) { 
      StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); 
      MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler); 
      // 分離代理對象鏈(由于目標(biāo)類可能被多個(gè)攔截器攔截,從而形成多次代理,通過下面的兩次循環(huán) 
      // 可以分離出最原始的的目標(biāo)類) 
      while (metaStatementHandler.hasGetter("h")) { 
        Object object = metaStatementHandler.getValue("h"); 
        metaStatementHandler = SystemMetaObject.forObject(object); 
      } 
      // 分離最后一個(gè)代理對象的目標(biāo)類 
      while (metaStatementHandler.hasGetter("target")) { 
        Object object = metaStatementHandler.getValue("target"); 
        metaStatementHandler = SystemMetaObject.forObject(object); 
      } 
      MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement"); 
      //分頁信息if (localPage.get() != null) { 
      Page page = localPage.get(); 
      BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql"); 
      // 分頁參數(shù)作為參數(shù)對象parameterObject的一個(gè)屬性 
      String sql = boundSql.getSql(); 
      // 重寫sql 
      String pageSql = buildPageSql(sql, page); 
      //重寫分頁sql 
      metaStatementHandler.setValue("delegate.boundSql.sql", pageSql); 
      Connection connection = (Connection) invocation.getArgs()[0]; 
      // 重設(shè)分頁參數(shù)里的總頁數(shù)等 
      setPageParameter(sql, connection, mappedStatement, boundSql, page); 
      // 將執(zhí)行權(quán)交給下一個(gè)攔截器 
      return invocation.proceed(); 
    } else if (invocation.getTarget() instanceof ResultSetHandler) { 
      Object result = invocation.proceed(); 
      Page page = localPage.get(); 
      page.setResult((List) result); 
      return result; 
    } 
    return null; 
  } 
 
  /** 
   * 只攔截這兩種類型的 
   * StatementHandler 
   * ResultSetHandler 
   * @param target 
   * @return 
   */ 
  @Override 
  public Object plugin(Object target) { 
    if (target instanceof StatementHandler || target instanceof ResultSetHandler) { 
      return Plugin.wrap(target, this); 
    } else { 
      return target; 
    } 
  } 
 
  @Override 
  public void setProperties(Properties properties) { 
 
  } 
 
  /** 
   * 修改原SQL為分頁SQL 
   * @param sql 
   * @param page 
   * @return 
   */ 
  private String buildPageSql(String sql, Page page) { 
    StringBuilder pageSql = new StringBuilder(200); 
    pageSql.append("select * from ( select temp.*, rownum row_id from ( "); 
    pageSql.append(sql); 
    pageSql.append(" ) temp where rownum <= ").append(page.getEndRow()); 
    pageSql.append(") where row_id > ").append(page.getStartRow()); 
    return pageSql.toString(); 
  } 
 
  /** 
   * 獲取總記錄數(shù) 
   * @param sql 
   * @param connection 
   * @param mappedStatement 
   * @param boundSql 
   * @param page 
   */ 
  private void setPageParameter(String sql, Connection connection, MappedStatement mappedStatement, 
                 BoundSql boundSql, Page page) { 
    // 記錄總記錄數(shù) 
    String countSql = "select count(0) from (" + sql + ")"; 
    PreparedStatement countStmt = null; 
    ResultSet rs = null; 
    try { 
      countStmt = connection.prepareStatement(countSql); 
      BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql, 
          boundSql.getParameterMappings(), boundSql.getParameterObject()); 
      setParameters(countStmt, mappedStatement, countBS, boundSql.getParameterObject()); 
      rs = countStmt.executeQuery(); 
      int totalCount = 0; 
      if (rs.next()) { 
        totalCount = rs.getInt(1); 
      } 
      page.setTotal(totalCount); 
      int totalPage = totalCount / page.getPageSize() + ((totalCount % page.getPageSize() == 0) ? 0 : 1); 
      page.setPages(totalPage); 
    } catch (SQLException e) { 
      logger.error("Ignore this exception", e); 
    } finally { 
      try { 
        rs.close(); 
      } catch (SQLException e) { 
        logger.error("Ignore this exception", e); 
      } 
      try { 
        countStmt.close(); 
      } catch (SQLException e) { 
        logger.error("Ignore this exception", e); 
      } 
    } 
  } 
 
  /** 
   * 代入?yún)?shù)值 
   * @param ps 
   * @param mappedStatement 
   * @param boundSql 
   * @param parameterObject 
   * @throws SQLException 
   */ 
  private void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, 
                Object parameterObject) throws SQLException { 
    ParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, boundSql); 
    parameterHandler.setParameters(ps); 
  } 
 
  /** 
   * Description: 分頁 
   * Author: liuzh 
   * Update: liuzh(2014-04-16 10:56) 
   */ 
  public static class Page<E> { 
    private int pageNum; 
    private int pageSize; 
    private int startRow; 
    private int endRow; 
    private long total; 
    private int pages; 
    private List<E> result; 
 
    public Page(int pageNum, int pageSize) { 
      this.pageNum = pageNum; 
      this.pageSize = pageSize; 
      this.startRow = pageNum > 0 ? (pageNum - 1) * pageSize : 0; 
      this.endRow = pageNum * pageSize; 
    } 
 
    public List<E> getResult() { 
      return result; 
    } 
 
    public void setResult(List<E> result) { 
      this.result = result; 
    } 
 
    public int getPages() { 
      return pages; 
    } 
 
    public void setPages(int pages) { 
      this.pages = pages; 
    } 
 
    public int getEndRow() { 
      return endRow; 
    } 
 
    public void setEndRow(int endRow) { 
      this.endRow = endRow; 
    } 
 
    public int getPageNum() { 
      return pageNum; 
    } 
 
    public void setPageNum(int pageNum) { 
      this.pageNum = pageNum; 
    } 
 
    public int getPageSize() { 
      return pageSize; 
    } 
 
    public void setPageSize(int pageSize) { 
      this.pageSize = pageSize; 
    } 
 
    public int getStartRow() { 
      return startRow; 
    } 
 
    public void setStartRow(int startRow) { 
      this.startRow = startRow; 
    } 
 
    public long getTotal() { 
      return total; 
    } 
 
    public void setTotal(long total) { 
      this.total = total; 
    } 
 
    @Override 
    public String toString() { 
      return "Page{" + 
          "pageNum=" + pageNum + 
          ", pageSize=" + pageSize + 
          ", startRow=" + startRow + 
          ", endRow=" + endRow + 
          ", total=" + total + 
          ", pages=" + pages + 
          '}'; 
    } 
  } 
} 

使用該攔截器首先需要在Mybatis配置中配置該攔截器:

<plugins> 
  <plugin interceptor="com.mybatis.util.PageHelper"></plugin> 
</plugins> 

配置攔截器的時(shí)候需要注意plugins的位置,plugins位置順序如下:

properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, plugins?, environments?, databaseIdProvider?, mappers? 

最后是調(diào)用該方法的例子代碼(Service層):

@Override 
public PageHelper.Page<SysLoginLog> findSysLoginLog(String loginIp, 
                     String username, 
                     String loginDate, 
                     String exitDate, 
                     String logerr, 
                     int pageNumber, 
                     int pageSize) throws BusinessException { 
  PageHelper.startPage(pageNumber,pageSize); 
  sysLoginLogMapper.findSysLoginLog(loginIp, username, loginDate, exitDate, logerr); 
  return PageHelper.endPage(); 
} 

從上面可以看到使用該插件使用起來是很簡單的,只需要在查詢前后使用PageHelper的startPage和endPage方法即可,中間代碼的調(diào)用結(jié)果已經(jīng)存在于Page的result中,如果你在一個(gè)返回一個(gè)結(jié)果的地方調(diào)用PageHelper,返回的結(jié)果仍然是一個(gè)List,取第一個(gè)值即可(我想沒人會(huì)在這種地方這么用,當(dāng)然這樣也不出錯(cuò))。

另外在startPage和endPage中間的所有mybatis代碼都會(huì)被分頁,而且PageHelper只會(huì)保留最后一次的結(jié)果,因而使用時(shí)需要保證每次只在其中執(zhí)行一個(gè)mybatis查詢,如果有多個(gè)分頁,請多次使用startPage和endPage。

由于這里只提供了Oracle的實(shí)現(xiàn),所以我希望參考該分頁插件實(shí)現(xiàn)的其他數(shù)據(jù)庫的讀者也能將相應(yīng)的代碼開源。

項(xiàng)目地址:http://xiazai.jb51.net/201612/yuanma/Mybatis_PageHelper_jb51.zip

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • mybatis中使用not?in與?in的寫法說明

    mybatis中使用not?in與?in的寫法說明

    這篇文章主要介紹了mybatis中使用not?in與?in的寫法說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 詳解Java的readBytes是怎么實(shí)現(xiàn)的

    詳解Java的readBytes是怎么實(shí)現(xiàn)的

    眾所周知,Java是一門跨平臺語言,針對不同的操作系統(tǒng)有不同的實(shí)現(xiàn),下面小編就來從一個(gè)非常簡單的api調(diào)用帶大家來看看Java具體是怎么做的吧
    2023-07-07
  • Java反射機(jī)制詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java反射機(jī)制詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java 反射機(jī)制。通俗來講呢,就是在運(yùn)行狀態(tài)中,我們可以根據(jù)“類的部分已經(jīng)的信息”來還原“類的全部的信息”。這篇文章給大家詳細(xì)介紹了java反射機(jī)制的知識,感興趣的朋友一起看看吧
    2017-06-06
  • javaweb圖書商城設(shè)計(jì)之用戶模塊(1)

    javaweb圖書商城設(shè)計(jì)之用戶模塊(1)

    這篇文章主要介紹了javaweb圖書商城設(shè)計(jì)之用戶模塊的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Java中ArrayList集合的常用方法大全

    Java中ArrayList集合的常用方法大全

    這篇文章主要給大家介紹了關(guān)于Java中ArrayList集合的常用方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • java DecimalFormat常用方法詳解

    java DecimalFormat常用方法詳解

    這篇文章主要為大家詳細(xì)介紹了java DecimalFormat的常用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • java事件處理模型知識點(diǎn)總結(jié)

    java事件處理模型知識點(diǎn)總結(jié)

    在本篇文章里小辮給大家分享的是一篇關(guān)于java事件處理模型知識點(diǎn)總結(jié)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2021-01-01
  • 三分鐘讀懂mybatis中resultMap和resultType區(qū)別

    三分鐘讀懂mybatis中resultMap和resultType區(qū)別

    這篇文章主要給大家介紹了mybatis中resultMap和resultType區(qū)別的相關(guān)資料,resultType和resultMap都是mybatis進(jìn)行數(shù)據(jù)庫連接操作處理返回結(jié)果的,需要的朋友可以參考下
    2023-07-07
  • Spring Boot如何使用EhCache演示

    Spring Boot如何使用EhCache演示

    這篇文章主要介紹了Spring Boot如何使用EhCache演示,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • java使用正則表達(dá)式判斷手機(jī)號的方法示例

    java使用正則表達(dá)式判斷手機(jī)號的方法示例

    這篇文章主要介紹了java使用正則表達(dá)式判斷手機(jī)號的方法,分析了手機(jī)號碼段的原理及java使用正則表達(dá)式針對手機(jī)號的匹配操作實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-06-06

最新評論