国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

MyBatis實現物理分頁的實例

2019-11-26 13:14:24
字體:
來源:轉載
供稿:網友

 MyBatis使用RowBounds實現的分頁是邏輯分頁,也就是先把數據記錄全部查詢出來,然在再根據offset和limit截斷記錄返回

為了在數據庫層面上實現物理分頁,又不改變原來MyBatis的函數邏輯,可以編寫plugin截獲MyBatis Executor的statementhandler,重寫SQL來執行查詢

下面的插件代碼只針對MySQL

plugin代碼

package plugin;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.Properties;import org.apache.ibatis.executor.parameter.ParameterHandler;import org.apache.ibatis.executor.statement.StatementHandler;import org.apache.ibatis.logging.Log;import org.apache.ibatis.logging.LogFactory;import org.apache.ibatis.mapping.BoundSql;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.plugin.Interceptor;import org.apache.ibatis.plugin.Intercepts;import org.apache.ibatis.plugin.Invocation;import org.apache.ibatis.plugin.Plugin;import org.apache.ibatis.plugin.Signature;import org.apache.ibatis.reflection.MetaObject;import org.apache.ibatis.reflection.factory.DefaultObjectFactory;import org.apache.ibatis.reflection.factory.ObjectFactory;import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;import org.apache.ibatis.session.Configuration;import org.apache.ibatis.session.RowBounds;/** * 通過攔截<code>StatementHandler</code>的<code>prepare</code>方法,重寫sql語句實現物理分頁。 * 老規矩,簽名里要攔截的類型只能是接口。 * */@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class})})public class PaginationInterceptor implements Interceptor {  private static final Log logger = LogFactory.getLog(PaginationInterceptor.class);  private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();  private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();  private static String DEFAULT_PAGE_SQL_ID = ".*Page$"; // 需要攔截的ID(正則匹配)  @Override  public Object intercept(Invocation invocation) throws Throwable {    StatementHandler statementHandler = (StatementHandler) invocation.getTarget();    MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY,        DEFAULT_OBJECT_WRAPPER_FACTORY);    RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds");    // 分離代理對象鏈(由于目標類可能被多個攔截器攔截,從而形成多次代理,通過下面的兩次循環可以分離出最原始的的目標類)    while (metaStatementHandler.hasGetter("h")) {      Object object = metaStatementHandler.getValue("h");      metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);    }    // 分離最后一個代理對象的目標類    while (metaStatementHandler.hasGetter("target")) {      Object object = metaStatementHandler.getValue("target");      metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);    }    // property在mybatis settings文件內配置    Configuration configuration = (Configuration) metaStatementHandler.getValue("delegate.configuration");    // 設置pageSqlId    String pageSqlId = configuration.getVariables().getProperty("pageSqlId");    if (null == pageSqlId || "".equals(pageSqlId)) {      logger.warn("Property pageSqlId is not setted,use default '.*Page$' ");      pageSqlId = DEFAULT_PAGE_SQL_ID;    }    MappedStatement mappedStatement = (MappedStatement)        metaStatementHandler.getValue("delegate.mappedStatement");    // 只重寫需要分頁的sql語句。通過MappedStatement的ID匹配,默認重寫以Page結尾的MappedStatement的sql    if (mappedStatement.getId().matches(pageSqlId)) {      BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");      Object parameterObject = boundSql.getParameterObject();      if (parameterObject == null) {        throw new NullPointerException("parameterObject is null!");      } else {        String sql = boundSql.getSql();        // 重寫sql        String pageSql = sql + " LIMIT " + rowBounds.getOffset() + "," + rowBounds.getLimit();        metaStatementHandler.setValue("delegate.boundSql.sql", pageSql);        // 采用物理分頁后,就不需要mybatis的內存分頁了,所以重置下面的兩個參數        metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);        metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);      }    }    // 將執行權交給下一個攔截器    return invocation.proceed();  }  @Override  public Object plugin(Object target) {    // 當目標類是StatementHandler類型時,才包裝目標類,否者直接返回目標本身,減少目標被代理的次數    if (target instanceof StatementHandler) {      return Plugin.wrap(target, this);    } else {      return target;    }  }  @Override  public void setProperties(Properties properties) {    //To change body of implemented methods use File | Settings | File Templates.  }}

配置plugin

  <plugins>    <plugin interceptor="plugin.PaginationInterceptor" />  </plugins>

查詢SQL

  <!-- 測試分頁查詢 -->  <select id="selectUserByPage" resultMap="dao.base.userResultMap">    <![CDATA[    SELECT * FROM user    ]]>  </select>

調用示例

  @Override  public List<User> selectUserByPage(int offset, int limit) {    RowBounds rowBounds = new RowBounds(offset, limit);    return getSqlSession().selectList("dao.userdao.selectUserByPage", new Object(), rowBounds);  }

另外,結合Spring MVC,編寫翻頁和生成頁碼代碼

頁碼類

package util;/** * Created with IntelliJ IDEA. * User: zhenwei.liu * Date: 13-8-7 * Time: 上午10:29 * To change this template use File | Settings | File Templates. */public class Pagination {  private String url; // 頁碼url  private int pageSize = 10; // 每頁顯示記錄數  private int currentPage = 1;  // 當前頁碼  private int maxPage = Integer.MAX_VALUE;  // 最大頁數  // 獲取offset  public int getOffset() {    return (currentPage - 1) * pageSize;  }  // 獲取limit  public int getLimit() {    return getPageSize();  }  public String getUrl() {    return url;  }  public void setUrl(String url) {    this.url = url;  }  public int getPageSize() {    return pageSize;  }  public void setPageSize(int pageSize) {    this.pageSize = pageSize;  }  public int getCurrentPage() {    return currentPage;  }  public void setCurrentPage(int currentPage) {    if (currentPage < 1)      currentPage = 1;    if (currentPage > maxPage)      currentPage = maxPage;    this.currentPage = currentPage;  }  public int getMaxPage() {    return maxPage;  }  public void setMaxPage(int maxPage) {    this.maxPage = maxPage;  }}

為了計算最大頁碼,需要知道數據表的總記錄數,查詢SQL如下

  <!-- 記錄總數 -->  <select id="countUser" resultType="Integer">    <![CDATA[    SELECT COUNT(*) FROM user    ]]>  </select>
 @Override  public Integer countTable() {    return getSqlSession().selectOne("dao.userdao.countUser");  }

Controller中的使用

  @RequestMapping("/getUserByPage")  public String getUserByPage(@RequestParam                  int page, Model model) {    pagination.setCurrentPage(page);    pagination.setUrl(getCurrentUrl());    pagination.setMaxPage(userDao.countTable() / pagination.getPageSize() + 1);    List<User> userList = userDao.selectUserByPage(        pagination.getOffset(), pagination.getLimit());    model.addAttribute(pagination);    model.addAttribute(userList);    return "index";  }

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 全州县| 宜黄县| 西盟| 连平县| 阿克苏市| 怀来县| 关岭| 西乡县| 尼玛县| 内丘县| 石首市| 石泉县| 丘北县| 衡阳县| 资溪县| 灵丘县| 娱乐| 南川市| 崇仁县| 福海县| 义马市| 托里县| 澜沧| 迁西县| 孟州市| 忻城县| 沙田区| 张家口市| 永吉县| 寿阳县| 陆川县| 江川县| 古蔺县| 淮北市| 达日县| 博客| 明光市| 视频| 察隅县| 中卫市| 江达县|