mybatis分頁

在做項目時,好多地方都會用到分頁,以前只是把別人封裝號的分頁拿過來用,從來沒有自己認真研究過,今天我在項目裏要自己開始寫了分頁了,在網上查了一下資料,再結合自己的項目,謝了一個簡單的分頁,主要有三塊核心內容,page實體類,mybatis攔截器,前臺實現分頁:

Page實體類代碼如下:

package com.hrtel.framework.util;

import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

public class Page {
	private static final Logger logger = Logger.getLogger(Page.class);
	private static ObjectMapper mapper = new ObjectMapper();

	private static String DEFAULT_PAGESIZE = "10";
	private int pageNo; // 當前頁碼
	private int pageSize; // 每頁行數
	private int totalRecord; // 總記錄數
	private int totalPage; // 總頁數
	private Map<String, String> params; // 查詢條件
	private Map<String, List<String>> paramLists; // 數組查詢條件
	private String searchUrl; // Url地址
	public Page() {
		pageNo = 1;
		pageSize = Integer.valueOf(DEFAULT_PAGESIZE);
		totalRecord = 0;
		totalPage = 0;
		params = Maps.newHashMap();
		paramLists = Maps.newHashMap();
		searchUrl = "";
	}

	public static Page newBuilder(int pageNo, int pageSize, String url) {
		Page page = new Page();
		page.setPageNo(pageNo);
		page.setPageSize(pageSize);
		page.setSearchUrl(url);
		return page;
	}

	/**
	 * 查詢條件轉json
	 * 
	 * @return
	 */
	public String getParaJson() {
		Map<String, Object> map = Maps.newHashMap();
		for (String key : params.keySet()) {
			if (params.get(key) != null) {
				map.put(key, params.get(key));
			}
		}
		String json = "";
		try {
			json = mapper.writeValueAsString(map);
		} catch (Exception e) {
			logger.error("轉換JSON失敗", e);
		}
		return json;
	}

	/**
	 * 數組查詢條件轉JSON
	 */
	public String getParaListJson() {
		Map<String, Object> map = Maps.newHashMap();
		for (String key : paramLists.keySet()) {
			List<String> lists = paramLists.get(key);
			if (lists != null && lists.size() > 0) {
				map.put(key, lists);
			}
		}
		String json = "";
		try {
			json = mapper.writeValueAsString(map);
		} catch (Exception e) {
			logger.error("轉換JSON失敗", e);
		}
		return json;
	}

	/**
	 * 總件數變化時,更新總頁數並計算顯示樣式
	 */
	public void refreshPage() {
		// 總頁數計算
		totalPage = totalRecord % pageSize == 0 ? totalRecord / pageSize : (totalRecord / pageSize + 1);
		// 防止超出最末頁(瀏覽途中數據被刪除的情況)
		if (pageNo > totalPage && totalPage != 0) {
			pageNo = totalPage;
		}
	}
	public int getPageNo() {
		return pageNo;
	}

	public void setPageNo(int pageNo) {
		this.pageNo = pageNo;
	}

	public int getPageSize() {
		return pageSize;
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	public int getTotalRecord() {
		return totalRecord;
	}

	public void setTotalRecord(int totalRecord) {
		this.totalRecord = totalRecord;
	}

	public int getTotalPage() {
		return totalPage;
	}

	public void setTotalPage(int totalPage) {
		this.totalPage = totalPage;
	}

	public Map<String, String> getParams() {
		return params;
	}

	public void setParams(Map<String, String> params) {
		this.params = params;
	}

	public Map<String, List<String>> getParamLists() {
		return paramLists;
	}

	public void setParamLists(Map<String, List<String>> paramLists) {
		this.paramLists = paramLists;
	}

	public String getSearchUrl() {
		return searchUrl;
	}

	public void setSearchUrl(String searchUrl) {
		this.searchUrl = searchUrl;
	}
}

哪個類需要用到分頁,就要在它的實體類裏面加上Page屬性:

private Page page;  //分頁

接下來是mybatis的攔截器:

package com.hrtel.framework.util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.JXPathNotFoundException;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.MappedStatement.Builder;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.SqlSource;
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.scripting.defaults.DefaultParameterHandler;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.log4j.Logger;

@Intercepts({@Signature(type=Executor.class,method="query",args={ MappedStatement.class, 
		Object.class, RowBounds.class, ResultHandler.class })})
public class PageInterceptor implements Interceptor{
	private static final Logger logger = Logger.getLogger(PageInterceptor.class);
	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		logger.info("*****into method intercept for mybatis plugin*****");
		//當前環境 MappedStatement,BoundSql,及sql取得  
		MappedStatement mappedStatement=(MappedStatement)invocation.getArgs()[0];
		Object parameter = invocation.getArgs()[1];
		BoundSql boundSql = mappedStatement.getBoundSql(parameter);
		String originalSql = boundSql.getSql().trim();
		Object parameterObject = boundSql.getParameterObject();
		//Page對象獲取,“信使”到達攔截器!  
	    Page page = searchPageWithXpath(boundSql.getParameterObject(),".","page","*/page");  
	    if (null != page){
	    	//Page對象存在的場合,開始分頁處理 
	    	String countSql = getCountSql(originalSql);  
	    	Connection connection=mappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection();
	    	PreparedStatement countStmt = connection.prepareStatement(countSql);
	    	BoundSql countBS = copyFromBoundSql(mappedStatement, boundSql, countSql);
	    	DefaultParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, countBS);
	    	parameterHandler.setParameters(countStmt);  
	        ResultSet rs = countStmt.executeQuery();  
	        int totpage=0;  
	        if (rs.next()) {    
	          totpage = rs.getInt(1);    
	        }  
	        rs.close();    
	        countStmt.close();    
	        connection.close();  
	          
	        //分頁計算  
	        page.setTotalRecord(totpage);  
	        page.refreshPage();
	        //對原始Sql追加limit  
	        int offset = (page.getPageNo() - 1) * page.getPageSize();  
	        StringBuffer sb = new StringBuffer();  
	        sb.append(originalSql).append(" limit ").append(offset).append(",").append(page.getPageSize());  
	        BoundSql newBoundSql = copyFromBoundSql(mappedStatement, boundSql, sb.toString());  
	        MappedStatement newMs = copyFromMappedStatement(mappedStatement,new BoundSqlSqlSource(newBoundSql));    
	        invocation.getArgs()[0]= newMs;    
	      }
	    logger.info("*******method intercept end**********");
	    return invocation.proceed();   
	}

	@Override
	public Object plugin(Object arg0) {
		return Plugin.wrap(arg0, this);
	}

	@Override
	public void setProperties(Properties arg0) {
		
	}
	
	/** 
	   * 根據給定的xpath查詢Page對象 
	   */  
	  private Page searchPageWithXpath(Object o,String... xpaths) {  
	    JXPathContext context = JXPathContext.newContext(o);  
	    Object result;  
	    for(String xpath : xpaths){  
	      try {  
	        result = context.selectSingleNode(xpath);  
	      } catch (JXPathNotFoundException e) {  
	        continue;  
	      }  
	      if ( result instanceof Page ){  
	        return (Page)result;  
	      }  
	    }  
	    return null;  
	  }
	  
	  /** 
	   * 根據原Sql語句獲取對應的查詢總記錄數的Sql語句 
	   */  
	  private String getCountSql(String sql) {  
	    return "SELECT COUNT(*) FROM (" + sql + ") aliasForPage";  
	  }  
	  /** 
	   * 複製BoundSql對象 
	   */  
	  private BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, String sql) {  
	    BoundSql newBoundSql = new BoundSql(ms.getConfiguration(),sql, boundSql.getParameterMappings(), boundSql.getParameterObject());  
	    for (ParameterMapping mapping : boundSql.getParameterMappings()) {  
	        String prop = mapping.getProperty();  
	        if (boundSql.hasAdditionalParameter(prop)) {  
	            newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));  
	        }  
	    }  
	    return newBoundSql;  
	  }
	  public class BoundSqlSqlSource implements SqlSource {    
	      BoundSql boundSql;    
	      public BoundSqlSqlSource(BoundSql boundSql) {    
	        this.boundSql = boundSql;    
	      }
	      public BoundSql getBoundSql(Object parameterObject) {    
	        return boundSql;    
	      }    
	  }
	  /** 
	   * 複製MappedStatement對象 
	   */  
	  private MappedStatement copyFromMappedStatement(MappedStatement ms,SqlSource newSqlSource) {  
	    Builder builder = new Builder(ms.getConfiguration(),ms.getId(),newSqlSource,ms.getSqlCommandType());  
	      
	    builder.resource(ms.getResource());  
	    builder.fetchSize(ms.getFetchSize());  
	    builder.statementType(ms.getStatementType());  
	    builder.keyGenerator(ms.getKeyGenerator());  
	    String [] s = ms.getKeyProperties(); 
	    if (null == s){
	    	builder.keyProperty(null);
	    }else{
	    	builder.keyProperty(s[0]);
	    }
	    builder.timeout(ms.getTimeout());  
	    builder.parameterMap(ms.getParameterMap());  
	    builder.resultMaps(ms.getResultMaps());  
	    builder.resultSetType(ms.getResultSetType());  
	    builder.cache(ms.getCache());  
	    builder.flushCacheRequired(ms.isFlushCacheRequired());  
	    builder.useCache(ms.isUseCache());  
	      
	    return builder.build();  
	  }  
}
寫了攔截器之後,需要在xml裏面註冊攔截器,我用的框架是springMVC+mybatis結合的,所以我就在spring-mybatis.xml中註冊自己的攔截器:

 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
        <property name="dataSource" ref="dataSource" />  
        <!-- 自動掃描mapping.xml文件 -->  
        <property name="configLocation"  value="classpath:sqlMapConfig.xml"/>
        <!-- 配置Mybatis的插件plugin -->
        <property name="plugins">
	        <array>
	            <bean class="com.hrtel.framework.util.PageInterceptor">
	                <property name="properties">
	                    <value>
	                        property-key=property-value
	                    </value>
	                </property>
	            </bean>
	        </array>
	    </property>
    </bean>  

寫完上面的之後,就需要寫前臺的js接收了:

function initPage(){
	var pageHtml = "";
	var pageNo = page.pageNo;
	var pageSize = page.pageSize;
	var totalPage = page.totalPage;
	var totalRecord = page.totalRecord;
	if (pageNo != 1){
		pageHtml += "<a href='#' οnclick='onclickMenu(1)' style='text-decoration: none'><b style='font-size: 12'>第一頁</b></a>  ";
		pageHtml += "<a href='#' οnclick='onclickMenu("+(pageNo-1)+")' style='text-decoration: none'><b style='font-size: 12'>上一頁</b></a>  ";
	}
	if (pageNo != totalPage){
		pageHtml += "<a href='#' οnclick='onclickMenu("+(parseInt(pageNo)+1)+")' style='text-decoration: none'><b style='font-size: 12'>下一頁</b></a>  ";
		pageHtml += "<a href='#' οnclick='onclickMenu("+(parseInt(totalPage))+")' style='text-decoration: none'><b style='font-size: 12'>最後一頁</b></a>  ";
	}
	pageHtml += "頁數:<label id='curpage' style='color: red; font-size: 13'>"+pageNo+"</label>/<label id='wholepages' style='color: red; font-size: 13'>"+totalPage+"</label>  ";
	pageHtml += "<input id='ppage' type='text' size='5'/><a οnclick='gotoPage()'>跳轉</a>  ";
	pageHtml += "<label>總條數:"+totalRecord+"</label>";
	$('#datePage').html("<tr><td>"+pageHtml+"</td></tr>");
}

每次點擊分頁裏面的按鈕時,都會調用onclickMenu()方法,這個方法主要封裝的是一個ajax,前臺向後臺發送請求:

function onclickMenu(pageNo){
	var startTime = $('#startTime').datebox('getValue');
	var endTime = $('#endTime').datebox('getValue');
	var citys_name = $('#citys_name').val();
	var ci = $('#ci').val();
	
	var consumptionFlow_size = $('#consumptionFlow_size').val();
	var IMSI = $('IMSI').val();
	var MSISDN = $('MSISDN').val();
	
	var resultConlection = $('#resultConlection').val();
	var datas = {"pageNo":pageNo, "treeId":nodeId, "startTime":startTime, "endTime":endTime,
			"citys_name":citys_name, "ci":ci, "consumptionFlow_size":consumptionFlow_size,
			"resultConlection":resultConlection, "IMSI":IMSI, "MSISDN":MSISDN};
	$.ajax({        
		type:'post',        
		url:path+'/multipleAnalyseController/selectTempManager.do',   
		dataType:'json',  
		async: false,
		data: datas,
		success:function(result){
			myStore.removeAll();
			dataSource = result.multipleAnalyseList;
			myStore.add(dataSource);
			page = result.page;
			initPage();
		}    
	});
}
後臺controller裏面接收參數以及封裝參數的方法:

@RequestMapping("selectTempManager")
	public ModelAndView selectTempManager(HttpServletRequest request, HttpServletResponse response,
			 @RequestParam(required = false, defaultValue = "1") int pageNo,
			 @RequestParam(required = false, defaultValue = "10") int pageSize) throws ParseException{
		logger.info("************************Thread into method selectTempManager*********************");
		String treeId = request.getParameter("treeId");
		

		Page page = Page.newBuilder(pageNo, pageSize, "selectTempManager");
		MultipleAnalyse multipleAnalyse = new MultipleAnalyse();
		
		multipleAnalyse.setNum1(treeId );
		multipleAnalyse.setPage(page);
		
		multipleAnalyseList = multipleAnalyseService.selectMultipleAnalyse(multipleAnalyse);
		
		Map<String,Object> attributes = new HashMap<String,Object>();
		attributes.put("multipleAnalyseList", multipleAnalyseList);
		attributes.put("page", page);
		MappingJacksonJsonView view = new MappingJacksonJsonView();
		view.setAttributesMap(attributes);
		ModelAndView mode = new ModelAndView();
		logger.info("************************select Flow analyse:"+multipleAnalyseList+"*********************");
		mode.setView(view);
		return mode;
	}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章