java分頁攔截類實(shí)現(xiàn)sql自動分頁
更新時(shí)間:2016年11月24日 11:28:27 作者:zcj2860755
這篇文章主要為大家詳細(xì)介紹了java分頁攔截類可以實(shí)現(xiàn)sql自動分頁,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
本文實(shí)例為大家分享了完整的java分頁攔截類,供大家參考,具體內(nèi)容如下
package com.opms.interceptor; 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.RowBounds; import com.wifi.core.page.Page; /** * 通過攔截<code>StatementHandler</code>的<code>prepare</code>方法,重寫sql語句實(shí)現(xiàn)物理分頁。 * 老規(guī)矩,簽名里要攔截的類型只能是接口。 * * @author 湖畔微風(fēng) * */ @Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class})}) public class PageInterceptor implements Interceptor { /** * 日志 */ private static final Log logger = LogFactory.getLog(PageInterceptor.class); /** * 聲明對象 */ private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory(); /** * 聲明對象 */ private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory(); /** * 數(shù)據(jù)庫類型(默認(rèn)為mysql) */ private static String defaultDialect = "mysql"; /** * 需要攔截的ID(正則匹配) */ private static String defaultPageSqlId = ".*4Page$"; /** * 數(shù)據(jù)庫類型(默認(rèn)為mysql) */ private static String dialect = ""; /** * 需要攔截的ID(正則匹配) */ private static String pageSqlId = ""; /** * @param invocation 參數(shù) * @return Object * @throws Throwable 拋出異常 */ public Object intercept(Invocation invocation) throws Throwable { StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY); // 分離代理對象鏈(由于目標(biāo)類可能被多個(gè)攔截器攔截,從而形成多次代理,通過下面的兩次循環(huán)可以分離出最原始的的目標(biāo)類) while (metaStatementHandler.hasGetter("h")) { Object object = metaStatementHandler.getValue("h"); metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY); } // 分離最后一個(gè)代理對象的目標(biāo)類 while (metaStatementHandler.hasGetter("target")) { Object object = metaStatementHandler.getValue("target"); metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY); } dialect=defaultDialect;pageSqlId=defaultPageSqlId; /* Configuration configuration = (Configuration) metaStatementHandler.getValue("delegate.configuration"); dialect = configuration.getVariables().getProperty("dialect"); if (null == dialect || "".equals(dialect)) { logger.warn("Property dialect is not setted,use default 'mysql' "); dialect = defaultDialect; } pageSqlId = configuration.getVariables().getProperty("pageSqlId"); if (null == pageSqlId || "".equals(pageSqlId)) { logger.warn("Property pageSqlId is not setted,use default '.*Page$' "); pageSqlId = defaultPageSqlId; }*/ MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement"); // 只重寫需要分頁的sql語句。通過MappedStatement的ID匹配,默認(rèn)重寫以Page結(jié)尾的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 { Object obj = metaStatementHandler .getValue("delegate.boundSql.parameterObject.page"); // 傳入了page參數(shù)且需要開啟分頁時(shí) if(obj!=null&&obj instanceof Page &&((Page)obj).isPagination()){ Page page = (Page) metaStatementHandler .getValue("delegate.boundSql.parameterObject.page"); String sql = boundSql.getSql(); // 重寫sql String pageSql = buildPageSql(sql, page); metaStatementHandler.setValue("delegate.boundSql.sql", pageSql); // 采用物理分頁后,就不需要mybatis的內(nèi)存分頁了,所以重置下面的兩個(gè)參數(shù) metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET); metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT); Connection connection = (Connection) invocation.getArgs()[0]; // 重設(shè)分頁參數(shù)里的總頁數(shù)等 setPageParameter(sql, connection, mappedStatement, boundSql, page); } } } // 將執(zhí)行權(quán)交給下一個(gè)攔截器 return invocation.proceed(); } /** * 從數(shù)據(jù)庫里查詢總的記錄數(shù)并計(jì)算總頁數(shù),回寫進(jìn)分頁參數(shù)<code>PageParameter</code>,這樣調(diào)用者就可用通過 分頁參數(shù) * <code>PageParameter</code>獲得相關(guān)信息。 * * @param sql 參數(shù) * @param connection 連接 * @param mappedStatement 參數(shù) * @param boundSql 綁定sql * @param page 頁 */ private void setPageParameter(String sql, Connection connection, MappedStatement mappedStatement, BoundSql boundSql, Page page) { // 記錄總記錄數(shù) String countSql = "select count(0) from (" + sql + ") as total"; 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.setTotalCount(totalCount); page.init(page.getCurPage(), page.getPageSize(), totalCount); } 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); } } } /** * 對SQL參數(shù)(?)設(shè)值 * * @param ps 參數(shù) * @param mappedStatement 參數(shù) * @param boundSql 綁定sql * @param parameterObject 參數(shù)對象 * @throws SQLException 拋出sql異常 */ private void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject) throws SQLException { ParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, boundSql); parameterHandler.setParameters(ps); } /** * 根據(jù)數(shù)據(jù)庫類型,生成特定的分頁sql * * @param sql 餐宿 * @param page 頁 * @return String */ private String buildPageSql(String sql, Page page) { if (page != null) { StringBuilder pageSql = new StringBuilder(); if ("mysql".equals(dialect)) { pageSql = buildPageSqlForMysql(sql, page); } else if ("oracle".equals(dialect)) { pageSql = buildPageSqlForOracle(sql, page); } else { return sql; } return pageSql.toString(); } else { return sql; } } /** * mysql的分頁語句 * * @param sql 參數(shù) * @param page 頁 * @return String */ public StringBuilder buildPageSqlForMysql(String sql, Page page) { StringBuilder pageSql = new StringBuilder(100); String beginrow = String.valueOf((page.getCurPage() - 1) * page.getPageSize()); pageSql.append(sql); pageSql.append(" limit " + beginrow + "," + page.getPageSize()); return pageSql; } /** * 參考hibernate的實(shí)現(xiàn)完成oracle的分頁 * * @param sql 參數(shù) * @param page 參數(shù) * @return String */ public StringBuilder buildPageSqlForOracle(String sql, Page page) { StringBuilder pageSql = new StringBuilder(100); String beginrow = String.valueOf((page.getCurPage() - 1) * page.getPageSize()); String endrow = String.valueOf(page.getCurPage() * page.getPageSize()); pageSql.append("select * from ( select temp.*, rownum row_id from ( "); pageSql.append(sql); pageSql.append(" ) temp where rownum <= ").append(endrow); pageSql.append(") where row_id > ").append(beginrow); return pageSql; } /** * @param target 參數(shù) * @return Object */ public Object plugin(Object target) { // 當(dāng)目標(biāo)類是StatementHandler類型時(shí),才包裝目標(biāo)類,否者直接返回目標(biāo)本身,減少目標(biāo)被代理的次數(shù) if (target instanceof StatementHandler) { return Plugin.wrap(target, this); } else { return target; } } /** * @param properties 參數(shù) */ public void setProperties(Properties properties) { } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
您可能感興趣的文章:
- java分頁工具類的使用方法
- Java分頁工具類及其使用(示例分享)
- 淺談java分頁三個(gè)類 PageBean ResponseUtil StringUtil
- 一個(gè)通用的Java分頁基類代碼詳解
- Java Web 簡單的分頁顯示實(shí)例代碼
- Java簡單實(shí)現(xiàn)SpringMVC+MyBatis分頁插件
- 舉例詳解用Java實(shí)現(xiàn)web分頁功能的方法
- 使用Jquery+Ajax+Json如何實(shí)現(xiàn)分頁顯示附JAVA+JQuery實(shí)現(xiàn)異步分頁
- java中利用List的subList方法實(shí)現(xiàn)對List分頁(簡單易學(xué))
- jsp+servlet+javabean實(shí)現(xiàn)數(shù)據(jù)分頁方法完整實(shí)例
- Java實(shí)現(xiàn)的分頁工具類與用法示例
相關(guān)文章
SpringBoot項(xiàng)目的測試類實(shí)例解析
這篇文章主要介紹了SpringBoot項(xiàng)目的測試類實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12Java老手該當(dāng)心的13個(gè)錯(cuò)誤
這篇文章主要介紹了Java老手該當(dāng)心的13個(gè)錯(cuò)誤,需要的朋友可以參考下2015-04-04Java實(shí)現(xiàn)高校教務(wù)系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)高校教務(wù)系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08java使用htmlparser提取網(wǎng)頁純文本例子
這篇文章主要介紹了java使用htmlparser提取網(wǎng)頁純文本例子,需要的朋友可以參考下2014-04-04SpringBoot各種參數(shù)校驗(yàn)的實(shí)例教程
經(jīng)常需要提供接口與用戶交互(獲取數(shù)據(jù)、上傳數(shù)據(jù)等),由于這個(gè)過程需要用戶進(jìn)行相關(guān)的操作,為了避免出現(xiàn)一些錯(cuò)誤的數(shù)據(jù)等,一般需要對數(shù)據(jù)進(jìn)行校驗(yàn),下面這篇文章主要給大家介紹了關(guān)于SpringBoot各種參數(shù)校驗(yàn)的相關(guān)資料,需要的朋友可以參考下2022-03-03詳解Spring MVC如何測試Controller(使用springmvc mock測試)
這篇文章主要介紹了詳解Spring MVC如何測試Controller(使用springmvc mock測試),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-12-12