多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php框架 > 框架設計 > 深入淺出Mybatis-分頁

深入淺出Mybatis-分頁

來源:程序員人生   發布時間:2017-03-20 09:51:41 閱讀次數:8299次

Mybatis的分頁功能很弱,它是基于內存的分頁(查出所有記錄再按偏移量和limit取結果),在大數據量的情況下這樣的分頁基本上是沒有用的。本文基于插件,通過攔截StatementHandler重寫sql語句,實現數據庫的物理分頁。本文適配的mybatis版本是3.2.2。

準備

為何在StatementHandler攔截

深入淺出MyBatis-Sqlsession章節介紹了1次sqlsession的完全履行進程,從中可以知道sql的解析是在StatementHandler里完成的,所以為了重寫sql需要攔截StatementHandler。

MetaObject簡介

在我的實現里大量使用了MetaObject這個對象,因此有必要先介紹下它。MetaObjectMybatis提供的1個的工具類,通過它包裝1個對象后可以獲得或設置該對象的本來不可訪問的屬性(比如那些私有屬性)。它有個3個重要方法常常用到:

1)       MetaObject forObject(Object object,ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory)

2)       Object getValue(String name)

3)       void setValue(String name, Object value)

方法1)用于包裝對象;方法2)用于獲得屬性的值(支持OGNL的方法);方法3)用于設置屬性的值(支持OGNL的方法);

插件的原理

參見深入淺出Mybatis-插件原理。

 

有了上面這些基礎知識的準備后,就能夠我們的主題了。

攔截器簽名

[java] view plain copy
  1. @Intercepts({@Signature(type =StatementHandler.class, method = "prepare", args ={Connection.class})})  
  2. publicclass PageInterceptor implementsInterceptor {  
  3. ...  
  4. }  

從簽名里可以看出,要攔截的目標類型是StatementHandler(注意:type只能配置成接口類型),攔截的方法是名稱為prepare參數為Connection類型的方法。

intercept的實現

[java] view plain copy
  1. public Object intercept(Invocation invocation) throws Throwable {  
  2.      StatementHandler statementHandler = (StatementHandler) invocation.getTarget();  
  3.      MetaObject metaStatementHandler = MetaObject.forObject(statementHandler,  
  4.      DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);  
  5.      // 分離代理對象鏈(由于目標類可能被多個攔截器攔截,從而構成屢次代理,通過下面的兩次循環  
  6.      // 可以分離出最原始的的目標類)  
  7.      while (metaStatementHandler.hasGetter("h")) {  
  8.          Object object = metaStatementHandler.getValue("h");  
  9.          metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY,   
  10.          DEFAULT_OBJECT_WRAPPER_FACTORY);  
  11.      }  
  12.      // 分離最后1個代理對象的目標類  
  13.      while (metaStatementHandler.hasGetter("target")) {  
  14.          Object object = metaStatementHandler.getValue("target");  
  15.          metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY,   
  16.          DEFAULT_OBJECT_WRAPPER_FACTORY);  
  17.      }  
  18.      Configuration configuration = (Configuration) metaStatementHandler.  
  19.      getValue("delegate.configuration");  
  20.      dialect = configuration.getVariables().getProperty("dialect");  
  21.      if (null == dialect || "".equals(dialect)) {  
  22.          logger.warn("Property dialect is not setted,use default 'mysql' ");  
  23.          dialect = defaultDialect;  
  24.      }  
  25.      pageSqlId = configuration.getVariables().getProperty("pageSqlId");  
  26.      if (null == pageSqlId || "".equals(pageSqlId)) {  
  27.          logger.warn("Property pageSqlId is not setted,use default '.*Page$' ");  
  28.          pageSqlId = defaultPageSqlId;  
  29.      }  
  30.      MappedStatement mappedStatement = (MappedStatement)   
  31.      metaStatementHandler.getValue("delegate.mappedStatement");  
  32.      // 只重寫需要分頁的sql語句。通過MappedStatement的ID匹配,默許重寫以Page結尾的  
  33.      //  MappedStatement的sql  
  34.      if (mappedStatement.getId().matches(pageSqlId)) {  
  35.          BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");  
  36.          Object parameterObject = boundSql.getParameterObject();  
  37.          if (parameterObject == null) {  
  38.              throw new NullPointerException("parameterObject is null!");  
  39.          } else {  
  40.              // 分頁參數作為參數對象parameterObject的1個屬性  
  41.              PageParameter page = (PageParameter) metaStatementHandler  
  42.                      .getValue("delegate.boundSql.parameterObject.page");  
  43.              String sql = boundSql.getSql();  
  44.              // 重寫sql  
  45.              String pageSql = buildPageSql(sql, page);  
  46.              metaStatementHandler.setValue("delegate.boundSql.sql", pageSql);  
  47.              // 采取物理分頁后,就不需要mybatis的內存分頁了,所以重置下面的兩個參數  
  48.              metaStatementHandler.setValue("delegate.rowBounds.offset",   
  49.              RowBounds.NO_ROW_OFFSET);  
  50.              metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);  
  51.              Connection connection = (Connection) invocation.getArgs()[0];  
  52.              // 重
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 亚洲播放 | 欧美一级aa免费毛片 | 国产精品嫩草影院视频 | 亚洲精品在线视频观看 | 亚洲 欧美 自拍 另类 | 国内久久精品 | 377p欧洲最大胆艺术 | 久久是精品 | 亚洲国产片 | 欧美成人 一区二区三区 | 波多野结衣中文一区二区免费 | 国产美女福利 | 久久精品视频9 | 亚洲精品国产一区二区在线 | 国产一级精品绿帽视频 | 亚洲成a人片在线观看www流畅 | 久久国产高清一区二区三区 | 欧美一级毛片高清视频 | 在线精品国精品国产不卡 | 亚洲福利在线视频 | 日本一级黄色毛片 | 在线观看日韩 | 午夜久久网 | xxxx18日本护士hd | 一级白嫩美女毛片免费 | 国产在线播放不卡 | 美女毛片免费 | 久久亚洲欧美综合激情一区 | a免费视频 | 99伊人| 亚洲国产二区三区久久 | 小说区 综合区 首页 | 国产一区二区在线视频播放 | 亚洲欧美在线综合一区二区三区 | 永久免费在线播放 | 男人午夜小视频 | 日本xxxxxxxxx18护士 | 久草在线成人 | 免费一级淫片aa | 五月天综合 | 欧美毛片在线观看 |