国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 詳解Mybatis極其(最)簡(好)單(用)的一個分頁插件

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

2020-07-19 12:24isea533 Java教程

這篇文章主要介紹了詳解Mybatis極其(最)簡(好)單(用)的一個分頁插件,非常具有實用價值,需要的朋友可以參考下。

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

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

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

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

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

先說實現方法,該插件只有一個類:PageHelper.Java

攔截器簽名為:

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
   * 修改原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方法中一個selelct count語句,這里也需要根據數據庫類型進行修改:

?
1
2
// 記錄總記錄數
String countSql = "select count(0) from (" + sql + ")";

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
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));
  }
 
  /**
   * 結束分頁并返回結果,該方法必須被調用,否則localPage會一直保存下去,直到下一次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);
      // 分離代理對象鏈(由于目標類可能被多個攔截器攔截,從而形成多次代理,通過下面的兩次循環
      // 可以分離出最原始的的目標類)
      while (metaStatementHandler.hasGetter("h")) {
        Object object = metaStatementHandler.getValue("h");
        metaStatementHandler = SystemMetaObject.forObject(object);
      }
      // 分離最后一個代理對象的目標類
      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");
      // 分頁參數作為參數對象parameterObject的一個屬性
      String sql = boundSql.getSql();
      // 重寫sql
      String pageSql = buildPageSql(sql, page);
      //重寫分頁sql
      metaStatementHandler.setValue("delegate.boundSql.sql", pageSql);
      Connection connection = (Connection) invocation.getArgs()[0];
      // 重設分頁參數里的總頁數等
      setPageParameter(sql, connection, mappedStatement, boundSql, page);
      // 將執行權交給下一個攔截器
      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();
  }
 
  /**
   * 獲取總記錄數
   * @param sql
   * @param connection
   * @param mappedStatement
   * @param boundSql
   * @param page
   */
  private void setPageParameter(String sql, Connection connection, MappedStatement mappedStatement,
                 BoundSql boundSql, Page page) {
    // 記錄總記錄數
    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);
      }
    }
  }
 
  /**
   * 代入參數值
   * @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配置中配置該攔截器:

?
1
2
3
<plugins>
  <plugin interceptor="com.mybatis.util.PageHelper"></plugin>
</plugins>

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
@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方法即可,中間代碼的調用結果已經存在于Page的result中,如果你在一個返回一個結果的地方調用PageHelper,返回的結果仍然是一個List,取第一個值即可(我想沒人會在這種地方這么用,當然這樣也不出錯)。

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

由于這里只提供了Oracle的實現,所以我希望參考該分頁插件實現的其他數據庫的讀者也能將相應的代碼開源。

項目地址:Mybatis_PageHelper.zip

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

原文鏈接:http://blog.csdn.net/isea533/article/details/23831273

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 一区久久 | 久免费视频 | av在线一区二区 | 欧美综合一区二区三区 | 欧美午夜精品久久久久久浪潮 | 性色网站 | 天天干夜干 | 日韩在线视频中文字幕 | 福利片在线观看 | 激情综合婷婷 | 精品黄色在线观看 | 久久久婷婷| 亚洲欧美日韩国产 | 亚洲精品国产综合99久久夜夜嗨 | 日韩免费视频 | 天堂资源在线 | av免费网站在线观看 | 国产日韩久久 | 日日精品 | 三级网站在线播放 | 日韩国产欧美一区 | 最近韩国日本免费观看mv免费版 | 亚洲欧美另类久久久精品2019 | 国产一区二区精品 | 亚洲视频免费 | 两性视频久久 | 日韩在线二区 | 精品免费在线 | 国产片在线观看免费观看 | 一二三四区视频在线观看 | 亚洲乱码国产乱码精品精98午夜 | 亚洲成人免费影院 | 伊人青青操 | 久久福利电影 | 免费观看一区二区三区 | 国产精品日产欧美久久久久 | 91精品国产综合久久香蕉最新版 | 欧美在线观看免费观看视频 | 欧美国产日韩一区二区三区 | 亚洲激情在线播放 | 亚洲欧美在线视频 |