java分页拦截类实现sql自动分页
本文实例为大家分享了完整的java分页拦截类,供大家参考,具体内容如下
packagecom.opms.interceptor; importjava.sql.Connection; importjava.sql.PreparedStatement; importjava.sql.ResultSet; importjava.sql.SQLException; importjava.util.Properties; importorg.apache.ibatis.executor.parameter.ParameterHandler; importorg.apache.ibatis.executor.statement.StatementHandler; importorg.apache.ibatis.logging.Log; importorg.apache.ibatis.logging.LogFactory; importorg.apache.ibatis.mapping.BoundSql; importorg.apache.ibatis.mapping.MappedStatement; importorg.apache.ibatis.plugin.Interceptor; importorg.apache.ibatis.plugin.Intercepts; importorg.apache.ibatis.plugin.Invocation; importorg.apache.ibatis.plugin.Plugin; importorg.apache.ibatis.plugin.Signature; importorg.apache.ibatis.reflection.MetaObject; importorg.apache.ibatis.reflection.factory.DefaultObjectFactory; importorg.apache.ibatis.reflection.factory.ObjectFactory; importorg.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory; importorg.apache.ibatis.reflection.wrapper.ObjectWrapperFactory; importorg.apache.ibatis.scripting.defaults.DefaultParameterHandler; importorg.apache.ibatis.session.RowBounds; importcom.wifi.core.page.Page; /** *通过拦截<code>StatementHandler</code>的<code>prepare</code>方法,重写sql语句实现物理分页。 *老规矩,签名里要拦截的类型只能是接口。 * *@author湖畔微风 * */ @Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class})}) publicclassPageInterceptorimplementsInterceptor{ /** *日志 */ privatestaticfinalLoglogger=LogFactory.getLog(PageInterceptor.class); /** *声明对象 */ privatestaticfinalObjectFactoryDEFAULT_OBJECT_FACTORY=newDefaultObjectFactory(); /** *声明对象 */ privatestaticfinalObjectWrapperFactoryDEFAULT_OBJECT_WRAPPER_FACTORY=newDefaultObjectWrapperFactory(); /** *数据库类型(默认为mysql) */ privatestaticStringdefaultDialect="mysql"; /** *需要拦截的ID(正则匹配) */ privatestaticStringdefaultPageSqlId=".*4Page$"; /** *数据库类型(默认为mysql) */ privatestaticStringdialect=""; /** *需要拦截的ID(正则匹配) */ privatestaticStringpageSqlId=""; /** *@paraminvocation参数 *@returnObject *@throwsThrowable抛出异常 */ publicObjectintercept(Invocationinvocation)throwsThrowable{ StatementHandlerstatementHandler=(StatementHandler)invocation.getTarget(); MetaObjectmetaStatementHandler=MetaObject.forObject(statementHandler,DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY); //分离代理对象链(由于目标类可能被多个拦截器拦截,从而形成多次代理,通过下面的两次循环可以分离出最原始的的目标类) while(metaStatementHandler.hasGetter("h")){ Objectobject=metaStatementHandler.getValue("h"); metaStatementHandler=MetaObject.forObject(object,DEFAULT_OBJECT_FACTORY,DEFAULT_OBJECT_WRAPPER_FACTORY); } //分离最后一个代理对象的目标类 while(metaStatementHandler.hasGetter("target")){ Objectobject=metaStatementHandler.getValue("target"); metaStatementHandler=MetaObject.forObject(object,DEFAULT_OBJECT_FACTORY,DEFAULT_OBJECT_WRAPPER_FACTORY); } dialect=defaultDialect;pageSqlId=defaultPageSqlId; /*Configurationconfiguration=(Configuration)metaStatementHandler.getValue("delegate.configuration"); dialect=configuration.getVariables().getProperty("dialect"); if(null==dialect||"".equals(dialect)){ logger.warn("Propertydialectisnotsetted,usedefault'mysql'"); dialect=defaultDialect; } pageSqlId=configuration.getVariables().getProperty("pageSqlId"); if(null==pageSqlId||"".equals(pageSqlId)){ logger.warn("PropertypageSqlIdisnotsetted,usedefault'.*Page$'"); pageSqlId=defaultPageSqlId; }*/ MappedStatementmappedStatement=(MappedStatement)metaStatementHandler.getValue("delegate.mappedStatement"); //只重写需要分页的sql语句。通过MappedStatement的ID匹配,默认重写以Page结尾的MappedStatement的sql if(mappedStatement.getId().matches(pageSqlId)){ BoundSqlboundSql=(BoundSql)metaStatementHandler.getValue("delegate.boundSql"); ObjectparameterObject=boundSql.getParameterObject(); if(parameterObject==null){ thrownewNullPointerException("parameterObjectisnull!"); }else{ Objectobj=metaStatementHandler .getValue("delegate.boundSql.parameterObject.page"); //传入了page参数且需要开启分页时 if(obj!=null&&objinstanceofPage&&((Page)obj).isPagination()){ Pagepage=(Page)metaStatementHandler .getValue("delegate.boundSql.parameterObject.page"); Stringsql=boundSql.getSql(); //重写sql StringpageSql=buildPageSql(sql,page); metaStatementHandler.setValue("delegate.boundSql.sql",pageSql); //采用物理分页后,就不需要mybatis的内存分页了,所以重置下面的两个参数 metaStatementHandler.setValue("delegate.rowBounds.offset",RowBounds.NO_ROW_OFFSET); metaStatementHandler.setValue("delegate.rowBounds.limit",RowBounds.NO_ROW_LIMIT); Connectionconnection=(Connection)invocation.getArgs()[0]; //重设分页参数里的总页数等 setPageParameter(sql,connection,mappedStatement,boundSql,page); } } } //将执行权交给下一个拦截器 returninvocation.proceed(); } /** *从数据库里查询总的记录数并计算总页数,回写进分页参数<code>PageParameter</code>,这样调用者就可用通过分页参数 *<code>PageParameter</code>获得相关信息。 * *@paramsql参数 *@paramconnection连接 *@parammappedStatement参数 *@paramboundSql绑定sql *@parampage页 */ privatevoidsetPageParameter(Stringsql,Connectionconnection,MappedStatementmappedStatement, BoundSqlboundSql,Pagepage){ //记录总记录数 StringcountSql="selectcount(0)from("+sql+")astotal"; PreparedStatementcountStmt=null; ResultSetrs=null; try{ countStmt=connection.prepareStatement(countSql); BoundSqlcountBS=newBoundSql(mappedStatement.getConfiguration(),countSql, boundSql.getParameterMappings(),boundSql.getParameterObject()); setParameters(countStmt,mappedStatement,countBS,boundSql.getParameterObject()); rs=countStmt.executeQuery(); inttotalCount=0; if(rs.next()){ totalCount=rs.getInt(1); } page.setTotalCount(totalCount); page.init(page.getCurPage(),page.getPageSize(),totalCount); }catch(SQLExceptione){ logger.error("Ignorethisexception",e); }finally{ try{ rs.close(); }catch(SQLExceptione){ logger.error("Ignorethisexception",e); } try{ countStmt.close(); }catch(SQLExceptione){ logger.error("Ignorethisexception",e); } } } /** *对SQL参数(?)设值 * *@paramps参数 *@parammappedStatement参数 *@paramboundSql绑定sql *@paramparameterObject参数对象 *@throwsSQLException抛出sql异常 */ privatevoidsetParameters(PreparedStatementps,MappedStatementmappedStatement,BoundSqlboundSql, ObjectparameterObject)throwsSQLException{ ParameterHandlerparameterHandler=newDefaultParameterHandler(mappedStatement,parameterObject,boundSql); parameterHandler.setParameters(ps); } /** *根据数据库类型,生成特定的分页sql * *@paramsql餐宿 *@parampage页 *@returnString */ privateStringbuildPageSql(Stringsql,Pagepage){ if(page!=null){ StringBuilderpageSql=newStringBuilder(); if("mysql".equals(dialect)){ pageSql=buildPageSqlForMysql(sql,page); }elseif("oracle".equals(dialect)){ pageSql=buildPageSqlForOracle(sql,page); }else{ returnsql; } returnpageSql.toString(); }else{ returnsql; } } /** *mysql的分页语句 * *@paramsql参数 *@parampage页 *@returnString */ publicStringBuilderbuildPageSqlForMysql(Stringsql,Pagepage){ StringBuilderpageSql=newStringBuilder(100); Stringbeginrow=String.valueOf((page.getCurPage()-1)*page.getPageSize()); pageSql.append(sql); pageSql.append("limit"+beginrow+","+page.getPageSize()); returnpageSql; } /** *参考hibernate的实现完成oracle的分页 * *@paramsql参数 *@parampage参数 *@returnString */ publicStringBuilderbuildPageSqlForOracle(Stringsql,Pagepage){ StringBuilderpageSql=newStringBuilder(100); Stringbeginrow=String.valueOf((page.getCurPage()-1)*page.getPageSize()); Stringendrow=String.valueOf(page.getCurPage()*page.getPageSize()); pageSql.append("select*from(selecttemp.*,rownumrow_idfrom("); pageSql.append(sql); pageSql.append(")tempwhererownum<=").append(endrow); pageSql.append(")whererow_id>").append(beginrow); returnpageSql; } /** *@paramtarget参数 *@returnObject */ publicObjectplugin(Objecttarget){ //当目标类是StatementHandler类型时,才包装目标类,否者直接返回目标本身,减少目标被代理的次数 if(targetinstanceofStatementHandler){ returnPlugin.wrap(target,this); }else{ returntarget; } } /** *@paramproperties参数 */ publicvoidsetProperties(Propertiesproperties){ } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。