참고 :이 블로그는 현재 페이징 플러그인과 완전히 다르므로 위의 프로젝트 주소를 통해 최신 소스 코드 및 문서를 확인하는 것이 좋습니다.
나는 전에 mybatis Pagination 쿼리에 대해 걱정했고 온라인으로 많은 관련 기사를 검색했지만 마지막 기사를 사용하지 않았습니다. PAGED 장소는 SQL과 Count SQL로 완전히 필기되어 매우 번거 롭습니다.
나중에 잠시 동안, 나는 Mybatis 내에서 Pagination 구현을 작성하고 싶었습니다. LanguageDriver를위한 구현을 썼습니다. 자동 페이지 매김에는 아무런 문제가 없지만 총 쿼리 수 (카운트)는 여전히 한 번에 해결 될 수 없으며 해결되지 않은 상태로 남겨졌습니다.
최근에, 나는 페이지 매김을 다시 사용해야합니다. 편의를 위해 일반 페이지 매김 수업을 작성해야하므로 인터넷에서 대부분의 Mybatis Pagination 코드를 다시 언급합니다.
실제로 오래 전에 누군가가 GitHub에서 소스 구현을 열었으며 MySQL, Oracle 및 SQLServer를 지원하는 소스 구현을 열었습니다. 이는 위의 참조와 유사하며보다 포괄적 인 고려 사항이 있습니다. 그러나 너무 많은 수업이 너무 귀찮은 일이라고 생각하기 때문에 실제로 두 개의 클래스로 나눌 수있는 인터셉터가 하나만있는 클래스를 구현했습니다. 수업 중 하나는 나에 의해 정적 클래스로 작성되어 인터셉터에 배치되었습니다. 페이지 클래스를 추출하여 페이지 사용을 용이하게 할 수도 있습니다.
먼저 구현 방법에 대해 이야기 해 봅시다. 이 플러그인에는 PageHelper.java의 클래스가 하나만 있습니다
인터셉터 서명은 다음과 같습니다.
}
여기의 서명은 전체 구현과 아이디어에 중요합니다. 먼저, Prepare Method를 가로 채면 Pagination SQL을 변경하고 쿼리를 계산합니다. 그런 다음 Handleresultsets 메소드를 가로 채어 마지막 처리 결과를 얻고 결과를 페이지 객체에 넣습니다.
다음은 페이지를 수정하는 코드이며, 이는 Oracle Data의 수정입니다. 다른 데이터베이스를 사용하는 경우 여기서 직접 코드를 수정할 수 있습니다.
/ ** * 원래의 SQL을 Pagination 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 ( ") 임시 rownum <=") .append (page.getendrow ()); pagesql.append ( ") where row_id>"). 반환 pagesql.tostring (); } 그런 다음 다음 setPageParameter 메소드에서 데이터베이스 유형에 따라 SELECT COUNT 문을 수정해야합니다.
// 레코드의 총 수 문자열 countsql = "(" + sql + ")에서 count (0)을 선택하십시오.다양한 데이터베이스를 지원하지 않는 이유는 무엇입니까? 나는 그것이 필요하다고 생각하지 않습니다. 일부 데이터베이스는 페이징을 지원하지 않으며이 플러그인이 더 간단할수록 개발자가 이해하고 수정하기가 더 쉬워집니다. 필요한 페이지 매김 쿼리로 수정하는 것은 확실히 문제가되지 않습니다.
마지막으로 전체 코드가 추가되었습니다 (계속 읽기, 아래 사용 방법도 있습니다) : (다운로드를 클릭하려면)
패키지 com.mybatis.util; import org.apache.ibatis.executor.parameter.parameterhandler; import org.apache.ibatis.executor.resultset.resultsethandler; import org.apache.ibatis.executor.statement.statemandler; 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.DefaultParameterAndler; import org.apache.log4j.logger; Java.sql.*; Java.util.list 가져 오기; java.util.properties import; /*** mybatis- Universal Pagination Interceptor* @author liuzh/abel533/isea* liuzh가 14-4-15에 생성했습니다. */ @Intercepts ({ @signature (type = stationhandler.class, method = "repary ="repars ", args = {connection.class}), @Signature (type = resultShandler.class, method ="handleresultsets ", args = {state.class})) 공개 클래스 PageHelper interceptor {private hintater interceptor = logger.getLogger (pageHelper.class); Public STATIC Final ThreadLocal <Page> localPage = New ThreadLocal <페이지> (); / ** * PAGEG 시작 * @param pagenum * @param pagesize */ public static void startPage (int pagenum, int pagesize) {localpage.set (새 페이지 (pagenum, pagesize)); } /*** 페이징을 끝내고 결과를 반환합니다. 방법은 호출되어야합니다. 그렇지 않으면 LocalPage는 다음 시작 페이지 * @return */ public static page endpage () {page page = localpage.get (); localpage.remove (); 반환 페이지; } @override public Object Intercept (호출 호출) 던지기 가능 {if (localpage.get () == null) {return invocation.proceed (); } if (invocation.getTarget () instanceof stateHandler) {stateHandler stateHandler = (stateHandler) invocation.getTarget (); MetaObject metastatementHandler = SystemMetaObject.forObject (StateHandler); // 프록시 객체 체인을 분리합니다 (대상 클래스가 다중 인터셉터에 의해 가로 채울 수 있기 때문에 다중 프록시가 형성되고 다음 두 루프가 형성되고 가장 원시적 인 대상 클래스가 분리 될 수 있습니다. metastatementHandler = SystemMetaObject.forObject (Object); } // 마지막 프록시 객체를 분리하는 대상 클래스 while metastatementHandler = SystemMetaObject.forObject (Object); } MAPPEDSTATEMENT MAPPEDSTATEMENT = (MAPPEDSTATEMENT) METASTATEMENTHANDLER.GETVALUE ( "Delegate.MappedStatement"); // 페이지 정보 if (localPage.get ()! = null) {page page = localpage.get (); BONDSQL BONDSQL = (BONDSQL) metastatementHandler.getValue ( "Delegate.BoundSql"); // PARAMERTOBJECT PARAMETERSTRING SQL = BONDSQL.GETSQL ()의 속성으로서 페이지 매개 변수; // SQL String Pagesql = BuildPagesQl (SQL, Page); // 페이징 SQL MECLASTATEMENDHANDLER.SETVALUE ( "Delegate.BoundSql.sql", pagesql); 연결 연결 = (Connection) invocation.getArgs () [0]; // 페이징 매개 변수 등의 총 페이지 수를 재설정합니다. SetPageParameter (SQL, Connection, MappedStatement, BoundSQL, Page); // 다음 인터셉터에 대한 실행 권한을 return.proceed (); } else if (invocation.getTarget () instanceof resultShandler) {object result = invocation.proceed (); 페이지 페이지 = localpage.get (); page.setResult ((목록) 결과); 반환 결과; } return null; } / ** *이 두 가지 유형의 * stateHandler * resultSENDANDLER * @Param target * / @ERVERRIDE public Object Plugin (Object Target) {if (target instanceof statehandler || recestEdandler의 대상 인스턴스) {return plugin.wrap (target, this); } else {반환 대상; }} @override public void setProperties (속성 속성) {} / ** * 원래 SQL을 Pagination으로 수정 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 ( ") 임시 rownum <=") .append (page.getendrow ()); pagesql.append ( ") where row_id>"). 반환 pagesql.tostring (); } / ** * 총 레코드 수를 가져옵니다 * @param sql * @param connection * @param mappedstatement * @param boundsql * / private void setpageparameter (string setpageparameter (문자열 sql, 연결 연결, mappedstatement mappappedstatement, boundsql boundsql, page page) {// 전체 번호 string (0) (0). ")"; 준비 상태 COUNTSTMT = NULL; resultSet rs = null; try {countstmt = connection.preparestatement (countsql); BONDSQL COUNTBS = NEW BONDSQL (MAPPEDSTATEMENT.GETCONFIGURATION (), COUNTSQL, BONDSQL.GETPARAMETERMAPPINGS (), BONDSQL.GETPARAMERTEROBJECT ()); 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 ( "이 예외를 무시", e); } 마침내 {try {rs.close (); } catch (sqlexception e) {logger.error ( "이 예외를 무시", e); } try {countstmt.close (); } catch (sqlexception e) {logger.error ( "이 예외를 무시", e); }}} / ** * 대체 매개 변수 값 * @param ps * @param mappedstatement * @param boundsql * @param parameterobject * @throws sqlexception * / private void setparameters (previdStatement ps, mappedStatement MappedStatement, bangeql bountql, Object ParameterObject) sqlemetermethermethmetermethermetmethmethermetmethmethmethmethomemetmethmethmethmetmethemence DefaultParameterAndler (MappedStatement, ParameterObject, BoundSQL); ParameterAndler.setParameters (ps); } / ** * 설명 : Pagination * 저자 : Liuzh * 업데이트 : liuzh (2014-04-16 10:56) * / public static 클래스 페이지 <e> {private int pagenum; Private int Pagesize; 개인 int Startrow; 개인 int endrow; 사적 긴 총계; 개인 int 페이지; 개인 목록 <E> 결과; 공개 페이지 (int pagenum, int pagesize) {this.pagenum = pagenum; this.pagesize = pagesize; this.startrow = pagenum> 0? (pagenum -1) * pagesize : 0; this.endrow = pagenum * pagesize; } 공개 목록 <E> getResult () {return result; } public void setResult (list <e> result) {this.result = result; } public int getPages () {반환 페이지; } public void setPages (int pages) {this.pages = pages; } public int getendrow () {return endrow; } public void etendrow (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 (긴 총) {this.total = Total; } @override public String toString () {return "page {" + "pagenum =" + pagenum + ", pagesize =" + pagesize + ", startrow =" + startrow + ", endrow =" + endrow + ", total =" + total + ", pages =" + pages + '}; }}} 이 인터셉터를 사용하려면 먼저 mybatis 구성에서 인터셉터를 구성해야합니다.
<플러그인> <플러그인 인터셉터 = "com.mybatis.util.pagehelper"> </plugin> </plugins>
인터셉터를 구성 할 때는 플러그인 위치에주의를 기울여야합니다. 플러그인의 순서는 다음과 같습니다.
Properties?, 설정?, 유형화?, 유형 핸들러?, ObjectFactory?, ObjectWrapperFactory?, 플러그인?, 환경?, DatabaseIdProvider?, 매퍼?
마지막 으로이 메소드를 호출하는 예제 코드 (서비스 계층)가 있습니다.
@override public pagehelper.page <sysloginlog> findsysloginLog (String loginip, String username, String logindate, String exitDate, String logerr, int pagenumber, int pageize) businessexception {pagehelper.startPage (pagenumber, pagesize); sysloginlogmapper.findsysloginlog (loginip, username, logindate, exitdate, logerr); return pageHelper.endPage (); }위에서 부터이 플러그인을 사용하는 것이 매우 간단하다는 것을 알 수 있습니다. 쿼리 전후 PageHelper의 시작 페이지 및 엔드 페이지 방법 만 사용하면됩니다. 중간 코드의 호출 결과는 이미 PageHelper의 결과에 존재합니다. 결과를 반환하는 장소에서 PageHelper를 호출하면 반환 된 결과는 여전히 목록이며, 첫 번째 값을 취할 수 있습니다 (아무도이 장소에서는 이런 식으로 사용하지 않을 것입니다. 물론 이런 식으로 오류가 없습니다).
또한 STARTPAGE와 ENDPAGE 사이의 모든 MyBatis 코드는 Paginated이며 PageHelper는 마지막 결과 만 유지합니다. 따라서 사용할 때는 한 번에 하나의 mybatis 쿼리 만 실행되도록해야합니다. 여러 페이징이있는 경우 STARTPAGE 및 ENDPAGE를 여러 번 사용하십시오.
여기에는 Oracle 구현 만 제공 되므로이 페이징 플러그인에서 구현 된 다른 데이터베이스를 참조하는 리더가 해당 코드를 오픈 할 수 있기를 바랍니다.
프로젝트 주소 : http://xiazai.vevb.com/201612/yuanma/mybatis_pagehelper_jb51.zip
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.