自己入手寫的mybatis分頁插件(極端復雜好用)。本站提示廣大學習愛好者:(自己入手寫的mybatis分頁插件(極端復雜好用))文章只能為提供參考,不一定能成為您想要的結果。以下是自己入手寫的mybatis分頁插件(極端復雜好用)正文
剛開端項目,需求用到mybatis分頁,網上看了很多插件,其實完成原理根本都迥然不同,但是大局部都只給了代碼,正文不全,所以參考了很多篇文章(每篇文章偷一點代碼,評出來自己的,半剽竊),才自己模擬著寫出了一個合適自己項目的分頁插件,話不多說,直接上代碼,相比大局部文章,正文算很完好了
最重要的阻攔器
package com.dnkx.interceptor;
import java.sql.*;
import java.util.HashMap;
import java.util.Properties;
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.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.SystemMetaObject;
import com.dnkx.pojo.Page;
/**
*
* 分頁阻攔器,用於阻攔需求停止分頁查詢的操作,然後對其停止分頁處置。
* 應用阻攔器完成Mybatis分頁的原理:
* 要應用JDBC對數據庫停止操作就必需要有一個對應的Statement對象,Mybatis在執行Sql語句前就會發生一個包括Sql語句的Statement對象,而且對應的Sql語句
* 是在Statement之前發生的,所以我們就可以在它生成Statement之前對用來生成Statement的Sql語句下手。在Mybatis中Statement語句是經過RoutingStatementHandler對象的
* prepare辦法生成的。所以應用阻攔器完成Mybatis分頁的一個思緒就是阻攔StatementHandler接口的prepare辦法,然後在阻攔器辦法中把Sql語句改成對應的分頁查詢Sql語句,之後再調用
* StatementHandler對象的prepare辦法,即調用invocation.proceed()。
* 關於分頁而言,在阻攔器外面我們還需求做的一個操作就是統計滿足以後條件的記載一共有多少,這是經過獲取到了原始的Sql語句後,把它改為對應的統計語句再應用Mybatis封裝好的參數和設
* 置參數的功用把Sql語句中的參數停止交換,之後再執行查詢記載數的Sql語句停止總記載數的統計。
*
* 解釋一下插件中能夠要用到的幾個類:
* MetaObject:mybatis提供的一個基於前往獲取屬性值的對象的類
* BoundSql : 在這個外面可以獲取都要執行的sql和執行sql要用到的參數
* MappedStatement : 這個可以失掉以後執行的sql語句在xml文件中配置的id的值
* RowBounds : 是mybatis內存分頁要用到的。
* ParameterHandler : 是mybatis中用來交換sql中?呈現的值的.
*
* @author 李小拐 2016年11月9日 10:59:04
*/
@Intercepts({
@Signature(type=StatementHandler.class,method="prepare",args={Connection.class}),
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class PageInterceptor implements Interceptor{
//阻攔分頁關鍵字
private static final String SELECT_ID="page";
//插件運轉的代碼,它將替代原有的辦法,要重寫最重要的intercept了
@Override
public Object intercept(Invocation invocation) throws Throwable {
if (invocation.getTarget() instanceof StatementHandler) {
//這裡我們有一個設定 假如查詢辦法含有Page 就停止分頁 其他辦法無視
//所以就要獲取辦法名
StatementHandler statementHandler=(StatementHandler)invocation.getTarget();
MetaObject metaObject=SystemMetaObject.forObject(statementHandler);
MappedStatement mappedStatement=(MappedStatement)metaObject.getValue("delegate.mappedStatement");
String selectId=mappedStatement.getId();
String methorName=selectId.substring(selectId.lastIndexOf(".")+1).toLowerCase();
//然後判別下 假如含有Page 就獲取sql
if(methorName.contains(SELECT_ID)){
BoundSql boundSql=(BoundSql)metaObject.getValue("delegate.boundSql");
//分頁參數作為參數對象parameterObject的一個屬性
String sql=boundSql.getSql();
System.out.println("獲取到的sql:"+sql);
HashMap<String, Object> map=(HashMap<String, Object>)(boundSql.getParameterObject());
//Page page=(Page)(boundSql.getParameterObject());
Page page=(Page)map.get("page");
// 重寫sql
String countSql=concatCountSql(sql);
String pageSql=concatPageSql(sql,page);
// System.out.println("重寫的 count sql :"+countSql);
System.out.println("重寫的 select sql :"+pageSql);
Connection connection = (Connection) invocation.getArgs()[0];
PreparedStatement countStmt = null;
ResultSet rs = null;
int totalCount = 0;
try {
countStmt = connection.prepareStatement(countSql);
rs = countStmt.executeQuery();
if (rs.next()) {
totalCount = rs.getInt(1);
}
} catch (SQLException e) {
System.out.println("Ignore this exception"+e);
} finally {
try {
rs.close();
countStmt.close();
} catch (SQLException e) {
System.out.println("Ignore this exception"+ e);
}
}
metaObject.setValue("delegate.boundSql.sql", pageSql);
//綁定count
page.setNumCount(totalCount);
}
}
return invocation.proceed();
}
// 阻攔類型StatementHandler,重寫plugin辦法
@Override
public Object plugin(Object target) {
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this);
}else {
return target;
}
}
@Override
public void setProperties(Properties properties) {
}
//改造sql
public String concatCountSql(String sql){
//StringBuffer sb=new StringBuffer("select count(*) from ");
/*sql=sql.toLowerCase();
if(sql.lastIndexOf("order")>sql.lastIndexOf(")")){
sb.append(sql.substring(sql.indexOf("from")+4, sql.lastIndexOf("order")));
}else{
sb.append(sql.substring(sql.indexOf("from")+4));
}*/
StringBuffer sb=new StringBuffer();
sql=sql.toLowerCase();
if(sql.lastIndexOf("order")>0){
sql=sql.substring(0,sql.indexOf("order"));
}
sb.append("select count(*) from ("+sql+") tmp");
return sb.toString();
}
public String concatPageSql(String sql,Page page){
StringBuffer sb=new StringBuffer();
sb.append(sql);
sb.append(" limit ").append(page.getPageBegin()).append(" , ").append(page.getPageSize());
return sb.toString();
}
}
分頁對象Page類
[java] view plain copy
package com.dnkx.pojo;
import java.util.HashMap;
import java.util.Map;
/**
*
* 分頁查詢輔佐類
* @author 李小拐 2016年11月9日 13:55:37
*/
public class Page {
//----------分頁-----------
private int pageSize;//每頁顯示條數
private int pageCurrentPage;//第幾頁
private int pageBegin;//開端地位
private int numCount;//總條數
private int pageTotal;//總條數
private String orderField = "";//控制排序頁面顯示的
private String orderDirection = "";
public Page(){
}
public Page(int pageSize, int pageCurrentPage) {
super();
this.pageSize = pageSize;
this.pageCurrentPage = pageCurrentPage;
}
public Page(Map<String, String> map){
if(map.get("pageNum")!=null){
this.setPageCurrentPage(this.pageCurrentPage = Integer.parseInt(map.get("pageNum")));//要查詢的頁數
}else{
this.setPageCurrentPage(1);//設置初始值
}
if(map.get("numPerPage")!=null){
this.setPageSize(Integer.parseInt(map.get("numPerPage")));//每頁顯示條數
}else{
this.setPageSize(5);//設置初始值
}
if(map.get("orderField")!=null){
this.setOrderField(map.get("orderField"));
}
if(map.get("orderDirection")!=null){
this.setOrderDirection(map.get("orderDirection"));
}
}
public int getPageCurrentPage() {
return pageCurrentPage;
}
public void setPageCurrentPage(int pageCurrentPage) {
this.pageCurrentPage = pageCurrentPage;
}
public int getNumCount() {
return numCount;
}
public void setNumCount(int numCount) {
this.numCount = numCount;
}
public int getPageTotal() {
return (numCount%pageSize>0)?(numCount/pageSize+1):(numCount/pageSize);
}
public void setPageTotal(int pageTotal) {
this.pageTotal = pageTotal;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getPageBegin() {
return pageSize*(pageCurrentPage-1);
}
public void setPageBegin(int pageBegin) {
this.pageBegin = pageBegin;
}
public String getOrderField() {
return orderField;
}
public void setOrderField(String orderField) {
this.orderField = orderField;
}
public String getOrderDirection() {
return orderDirection;
}
public void setOrderDirection(String orderDirection) {
this.orderDirection = orderDirection;
}
public static Page getPage(int pageSize, int pageCurrentPage){
return new Page(pageSize,pageCurrentPage);
}
public static Page getPage(Map map){
return new Page(map);
}
}
Controller外面調用方式
public String list(HttpServletRequest request) {
long a=System.currentTimeMillis();
HashMap<String,Object> map=GetRequestMap.getMap(request);//自己封裝的辦法,取request的參數
Page page= Page.getPage(map);//初始化page
map.put("page", page);//把page對象放入參數集合(這個map是mybatis要用到的,包括查詢條件,排序,分頁等)
//控制排序頁面顯示的
map.put(map.get("orderField")+"", map.get("orderDirection"));
List<Employee> list=employeeService.getListPage(map);
request.setAttribute("emlist", list);
request.setAttribute("page", page);
request.setAttribute("map", map);
//取page相關屬性
page.getNumCount();//總條數
page.getPageTotal();//總頁數
long b=System.currentTimeMillis();
System.out.println("---------耗時:"+(b-a)+"ms");
return "basic/employee_list";
}
最後,spring外面配置插件
<bean id="PageInterector" class="com.dnkx.interceptor.PageInterceptor"></bean> <!-- spring和MyBatis完滿整合,不需求mybatis的配置映射文件 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 自動掃描mapping.xml文件 --> <property name="mapperLocations" value="classpath:com/dnkx/mapping/*.xml"></property> <property name="plugins"> <ref bean="PageInterector"/> </property> </bean>
好了,到此完畢,本文僅供參考!也等待大神提意見