다음 페이지의 아이디어에 따르면 MyBitas의 다중 테넌트 설계를 쉽게 구현할 수 있습니다.
Mybatis가 제공하는 인터셉터를 사용하십시오. PAGED SQL 문은 캡슐화를 통해 다른 PAGED SQL로 처리됩니다.
이 예제는 MySQL과 Oracle의 Pagination 기능을 구현했습니다. 다음 견적 패키지에주의를 기울이고 인용하지 마십시오.
import java.sql.connection; import java.sql.preparedstatement; import java.sql.resultset; import java.sql.sqlexception; import java.util.list; import java.util.properties; import org.apache.ibatis.executor.parametarmeter.paramethinder; org.apache.ibatis.executor.statement.routingstatementhandler; import org.apache.ibatis.executor.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.statement.tatement 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 com.yidao.utils.page; import com.yidao.utils.reflecthelper;/** * * Pagination Interceptor, Paging Query가 필요한 작업을 인터셉트하는 데 사용됩니다. * mybatis 페이징의 원리는 인터셉터를 사용하여 구현됩니다. * JDBC를 사용하여 데이터베이스에서 작동하려면 해당 명령문 객체가 있어야합니다. Mybatis가 SQL 문을 실행하기 전에 SQL 문이 포함 된 명령문 객체를 생성하고 해당 SQL 문*가 문 앞에 생성되므로 문을 생성하기 전에 명령문을 생성하는 데 사용되는 SQL 문으로 시작할 수 있습니다. mybatis에서 명령문은 lourlingstatementhandler 객체의 * 준비 방법에 의해 생성됩니다. 따라서 인터셉터를 사용하여 MyBatis 페이징을 구현하기위한 아이디어 중 하나는 StateHandler 인터페이스의 준비 메소드를 가로 채고 SQL 문을 인터셉터 메소드에서 해당 Pagtination 쿼리 SQL 문으로 변경 한 다음 * StateHandler 객체의 준비 방법을 호출하는 것입니다. * Pagination의 경우 인터셉터에서해야 할 작업 중 하나는 현재 조건을 충족하는 총 레코드 수를 계산하는 것입니다. 이는 원래 SQL 문을 얻고 해당 통계 문으로 변경 한 다음 MyBatis 캡슐화 된 매개 변수 및 설정 * 매개 변수를 사용하여 SQL 문의 매개 변수를 교체하는 것입니다. 그런 다음 레코드 수를 쿼리하는 SQL 문이 실행되어 총 레코드 수를 계산합니다. * */ @Intercepts ({ @signature (type = stationhandler.class, method = "repary", args = {connection.class})}) public class pageinterceptor implements interceptor {private String dialect = ""; // 데이터베이스 방언 개인 문자열 pagesqlid = ""; // mapper.xml (일반 일치)에서 가로 채워야하는 ID 공개 객체 인터셉트 (호출) 던지기 가능 {// 실제로는 StateHandler에 대한 두 개의 구현 클래스 만 있습니다. // BasestatementHandler에는 3 개의 서브 클래스, 즉 SimpleStatementHandler, PreparedStatementHandler 및 CallableStatementHandler가 있습니다. // SimpleStatementHandler는 명령문을 처리하는 데 사용되며, PreparedStatementHandler 핸들이 준비된 상태이며 CallablestatementHandler는 // Processes CallAbleStatement입니다. MyBatis는 SQL 문을 처리 할 때 라우팅 스테이트 핸들러를 만듭니다. RoutingStatementHandler에는 // StateHandler 유형의 대의원 속성이 있습니다. RoutingStatementHandler는 다른 진술, 즉 SimpleStatementHandler, // preadtatementHandler 또는 CallableStatementHandler에 따라 해당 BasestatementHandler를 생성합니다. 라우팅 스테이트 핸들러에서 모든 StationHandler 인터페이스 메소드는 호출 대의원에 해당하는 대의원에 의해 구현됩니다. // 인터셉터가 PageInterceptor 클래스에서 @Signature와 StateHandler 인터페이스의 준비 메소드 만 인터셉터 만 표시했습니다. MyBatis는 RoutingStatementHandler를 설정할 때 인터셉터 플러그인 메소드를 통해서만 랩핑하므로 여기서 차단하는 대상 객체는 RoutingStatementHandler 객체 여야합니다. if (invocation.getTarget () RoutingStatementHandler) {RoutingStatementHandler StateHandler = (RoutingStatementHandler) invocation.getTarget (); StateHandler Delegate = (StateHandler) ReflecThelper.getFieldValue (StateHandler, "Delegate"); BONDSQL BONDSQL = DELEGATE.GETBOUNDSQL (); Object obj = boundsql.getParameterObject (); if (obj instanceof page <?>) {page <?> page = (page <?>) obj; // 대의원 클래스 맵핑 스테이션 매핑 된 스테이트의 기본 확장 핸들러의 매핑 된 속성을 검색합니다. // 가로 채기 된 준비 메소드의 매개 변수는 연결 객체 연결 연결 = (Connection) invocation.getArgs () [0]; // 현재 실행 된 SQL 문을 가져옵니다. 즉, Mapper 매핑 명령문 string sql = boundsql.getSql ()에 직접 쓴 SQL 문을 가져옵니다. // 현재 페이지 매개 변수 객체에 대한 총 레코드 수를 설정하십시오. // PAGED SQL 문자열 pagesql = this.getPagesQl (page, sql)을 가져옵니다. // 반사를 사용하여 현재 BoundSQL에 해당하는 SQL 속성을 설정하여 reflectelper.setfieldValue (boundsql, "sql", pagesql)에 대한 좋은 paged sql 문을 만듭니다. }} return invocation.proceed (); } /*** 현재 매개 변수 개체 페이지에 대한 총 레코드 수를 설정하십시오.* @param 페이지 매퍼 매핑 명령문* @param 맵핑 스타핑 매핑 명령문* @param 연결 현재 데이터베이스 연결* /private void settotalRecord (page <?> 페이지, 매핑 스테이트 매핑, 연결) 이 boundsql은 실제로 StateHandler를 사용하여 얻은 BoundSQL과 동일한 객체입니다. // Delegate의 BONDSQL은 MAPPEDSTATEMEN.GETBOUNDSQL (PARAMOBJ) 메소드를 통해 얻습니다. BONDSQL BONDSQL = MAPPEDSTATEMENT.GETBOUNDSQL (페이지); // 해당 SQL 문자열 sql = boundsql.getSql ()을 가져옵니다. // sql 문자열 countsql = this.getCountsQL (sql)을 쿼리하여 총 레코드 수를 계산하는 해당 SQL 문을 가져옵니다. // boundsql 목록을 통해 해당 매개 변수 맵을 가져옵니다. <ParametErmpaping> parameterMappings = boundsql.getParameterMappings (); // 쿼리 쿼리, 매개 변수 매핑 관계 매개 변수 객체 페이지를 쿼리 레코드에 해당하는 BONDSQL 객체를 만듭니다. BONDSQL COUNTBOUNDSQL = NEW BONDSQL (MAPPEDSTATEMENT.GETCONFIGURATION (), COUNTSQL, PARAMETERMAPPINGS, PAGE); // 매핑 스테이트, 매개 변수 객체 페이지 및 BONDSQL 객체 COUNTBOUNDSQL을 통해 매개 변수를 설정하기 위해 매개 변수 핸들러 객체를 만듭니다. ParameterAndler ParameterAndler = 새로운 DefaultParameterAndler (MappedStatement, Page, CountBoundSQL); // 연결을 통한 COUNTSQL에 해당하는 준비 상태 객체를 만듭니다. 준비된 상태 PSTMT = NULL; resultSet rs = null; try {pstmt = connection.preparestatement (countsql); // parameterHandler.setParameters (pstmt)를 통해 준비 상태 대상에 대한 매개 변수 설정 ParameterAndler; // 그런 다음 총 레코드 수를 얻고 결과를 얻기 위해 실행됩니다. rs = pstmt.executeQuery (); if (rs.next ()) {int totalrecord = rs.getint (1); // 현재 매개 변수 페이지에 대한 총 레코드 수를 설정합니다. }} catch (sqlexception e) {e.printstacktrace (); } 마침내 {try {if (rs! = null) rs.close (); if (pstmt! = null) pstmt.close (); } catch (sqlexception e) {e.printstacktrace (); }}} / ** * 쿼리에서 해당 총 레코드 수를 얻는 SQL 문 * @param sql * @return * / private String getCountsQl (String SQL) {int index = sql.indexof ( "from"); "select count (*)" + sql.substring (index)을 반환합니다. } /*** 페이지 객체를 기반으로 해당 페이지 매김 쿼리 SQL 문을 가져옵니다. 여기에는 두 개의 데이터베이스 유형만이 여기에 있습니다. MySQL 및 Oracle * 다른 데이터베이스는 * * @param 페이지 페이징 개체 * @param sql Original SQL 문 * @return */ private String getPagesQL (page <?> page, String SQL) {StringBuffer sqlbuffer = new StringBuffer (sql); if ( "mysql".equalsignorecase (delect)) {return getMysqlPagesQL (Page, SqlBuffer); } else if ( "Oracle".EqualSignoreCase (dialect)) {return getoraclePagesQL (Page, SqlBuffer); } return sqlbuffer.toString (); } / *** MySQL 데이터베이스에 대한 PAGED 쿼리 명령문을 가져옵니다* @Param 페이지 페이징 개체* @Param SQLBUFFER StringBuffer 객체가 포함되어 있습니다. MySQL의 레코드 위치는 0. // system.out.println에서 시작합니다 ( "page :"+page.getPage ()+"--------"+page.getrows ()); int offset = (page.getPage () -1) * page.getRows (); sqlbuffer.append ( "Limit") .Append (Offset) .append ( ","). Append (page.getRows ()); 반환 sqlbuffer.toString (); } / *** Oracle Database에 대한 PAGED 쿼리 명령문을 가져옵니다* @Param Page Paging Object* @Param SQLBuffer StringBuffer Object Oracle Database* / PRIVATION STRING GETORACLEPAGES SQL (Page <?> Page, StringBuffer SQLBuffer) {// 계산. Oracle Pagination은 Rownum을 통해 수행되며 Rownum은 1 int offset = (page.getPage () -1) * page.getRows () + 1; sqlbuffer.insert (0, "select u.*, rownum r from (") .append ( ") u where rownum <") .append (오프셋 + page.getrows ()); sqlbuffer.insert (0, "select * from (") .append ( ") where r> =") .append (오프셋); // 위의 SQL 문은 다음과 같습니다. // 선택 * from (select u. *, rownum r from (select * from t_user) u where rownum <31) 여기서 r> = 16 return sqlbuffer.toString (); } / *** 인터셉터에 해당하는 원래 객체를 캡슐화하는 메소드* / public 객체 플러그인 (Object Arg0) {// todo 자동 생성 메소드 스텁 if (arg0 instanceof statehandler) {return plugin.wrap (arg0, this); } else {return arg0; }} / *** 인터셉터를 등록 할 때 설정된 속성 설정* / public void setProperties (속성 p) {} public String getDialect () {return dialct; } public void setDialect (String Dialect) {this.dialect = dialect; } public String getPagesQlid () {return pagesqlid; } public void setPagesQLID (String PagesQLID) {this.PagesQLID = PagesQLID; }} XML 구성 :
<!-MyBatis 인터페이스 프로그래밍 구성-> <ean> <!-BasePackage 스캔 할 패키지를 지정합니다. 이 패키지 아래의 매퍼들이 검색됩니다. 쉼표 또는 세미콜론으로 여러 패키지를 지정할 수 있습니다-> <속성 이름 = "basepackage"value = "com.yidao.mybatis.dao" /> <property name = "sqlsessionfactorybeanname"value = "sqlsession factory" /> < /bean> <!-MyBatis Pagnination Intercepor-> <idipination = ""dix incation "> value = "mysql"/> <!-mapper.xml 파일에 쿼리 문자가 포함 된 ID와 명령문을 가로 채기-> <property name = "pagesqlid"value = ".*query $"/> </bean>
페이지 수업
package com.yidao.utils;/** 직접 살펴보십시오. 개인 정수 페이지 = 1; 개인 정수 TotalRecord; 공개 정수 getrows () {반환 행; } public void setrows (정수 행) {this.rows = 행; } public Integer getPage () {반환 페이지; } public void setPage (정수 페이지) {this.page = page; } public Integer getTotalRecord () {return totalrecord; } public void settotalRecord (정수 TotalRecord) {this.totalRecord = TotalRecord; }} Reflecthelper 클래스
package com.yidao.utils; import java.lang.reflect.field; import org.apache.commons.lang3.reflect.fieldutils; public class reflecthelper {public static 객체 getfieldValue (Object obj, String fieldname) {if (if (obj == null) {return null; } field targetfield = getTargetField (obj.getClass (), FieldName); try {return fieldutils.readfield (Targetfield, OBJ, True); } catch (delegalAccessException e) {e.printstacktrace (); } return null; } public static field getTargetfield (class <?> targetclass, String FieldName) {field field = null; try {if (targetclass == null) {return field; } if (object.class.equals (TargetClass)) {return 필드; } field = fieldUtils.getDeclaredField (TargetClass, FieldName, True); if (field == null) {field = getTargetField (TargetClass.getSuperClass (), FieldName); }} catch (예외 e) {} 반환 필드; } public static void setfieldValue (Object OBJ, String FieldName, Object Value) {if (null == obj) {return;} field targetfield = getTargetField (obj.getClass (), fieldName); try {fieldutils.writefield (Targetfield, obj, value); } catch (delegalAccessException e) {e.printstacktrace (); }}}위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.