MyBatis Paginationエントリポイント
MyBatisにはプラグイン(プラグイン)の概念がありますが、これは本質的にインターセプターのアイデアです。特定の分析は、別の記事でMyBatis迎撃者の原則に関する研究に記載されています。これに基づいて、この記事は、実際のプロジェクトの実装コードとその他の関連分析を直接表示します。
ページング固有のコード実装
まず、方言抽象クラスを定義して、ページネーションabstractdialect.javaを実装できます
パブリックアブストラクトクラスAbstractDialect { / ***制限とオフセットがサポートされているかどうか* @return* / public Abstract boolean supportlimitoffset(); / ** *制限がサポートされているかどうか * @return */ public abstract boolean supportlimit(); / ** *ページング属性を追加した後にSQLを取得 * @param sql * @param offset * @param limit * @return */ public abstract string getlimitstring(string sql、int offset、int limit);}さらに、OracleとMySQLデータベースのページページングテクノロジーを個別に実装します。
mysqldialect.java-mysqlページネーション方言
パブリッククラスmysqldialectはabstractdialectを拡張します{public boolean supportslimitoffset(){return true; } public boolean supportslimit(){return true; } public String getLimitString(String SQL、int offset、int limit){if(offset> 0){return sql + "limit" + offset + "、" + lime; } else {return sql + "lime" + limit; }}}oracledialect.java-oracle方言の実装
Public Class oracledialectはadialectを拡張します{@override public boolean supportlimitoffset(){return false; } @Override public boolean supportlimit(){return false; } @Override public String getLimitString(string sql、int start、int limit){if(start <0){start = 0; } if(limit <0){limit = 10; } stringbuilder pagesql = new StringBuilder(100); pagesql.append( "select * from(select temp。 *、rownum row_id from("); pagesql.append(sql); pagesql.append( ")temp where rownum <=")。(start+lime); pagesql.append( ")where row_id>")。 pagesql.toString()を返します。 }}対応するMyBatisプラグインインターセプターの実装は次のとおりです。InterceptStatementHandler#prepare(connection con)SQL Statementオブジェクトメソッドを作成する
PaginationInterceptor.java
@intercepts({@signature(type = statementhandler.class、method = "prepare"、args = {connection.class})})public final class paginateinterceptor Interceptor {private final static logger log = loggeractory .getLogger(paginationinterceptor.class);プライベートアディアレクト方言; public void setdialect(adialect方言){this.dialect = dialect; } @Override public Object intercept(呼び出しの呼び出し)スロー可能{//インターセプトされたオブジェクトを直接取得します。これにより、クラスRoutingStatementHandler StatementHandler StatementHandler =(StatementHandler)rkocation .getTarget(); bundsql bundsql = statementhandler.getBoundsql(); //主にStatementHandlerに関連付けられたオブジェクトと属性を取得するために主にMetaObjectを取得しますMetaObject MetastatementHandler = MetaObject.ForObject(StatementHandler、new DefaultObjectFactory()、new DefaultObjectWrapperfactory(); MappedStatement MappedStmt =(MappedStatement)MetastatementHandler .GetValue( "Delegate.MappedStatement" .intern()); // queryPagination()メソッドのみをpaginate if(mappedstmt.getid()。 } //ページングSQL文字列ORIGINALSQL =(STRING)METASTATEMENTHANDLER .GETVALUE( "DELEGATE.BOUNDSQL.SQL" .INTERN()); MetastatementHandler.setValue( "Delegate.Boundsql.sql" .intern()、dialect .getlimitstring(originalalsQl、rowbounds.getoffset()、rowbounds.getlimit())); MetastatementHandler.setValue( "Delegate.RowBounds.Offset" .intern()、rowbounds.no_row_offset); MetastatementHandler.setValue( "Delegate.RowBounds.limit" .intern()、rowbounds.no_row_limit); log.debug( "page sql:" + boundsql.getsql()); returnInvocation.proceed(); } // Object @override public object plugin(object target){return plugin.wrap(target、this); } @Override public void setProperties(プロパティプロパティ){}}スプリングの対応するXML構成は次のとおりであり、Oracle Paginationを例にとらえます
<! - Oracle Paginationに使用されるOracle方言の構成 - > <Bean Id = "PaginationInterceptor"> <プロパティ名= "Dialect"> <Bean/> </property> </bean>
上記のコードと構成を使用して、OracleデータベースとMySQLデータベースのページネーション操作を完了します。ブロガーはポイントの1つを分析します
MyBatis#MetaObject-Metadataオブジェクト分析
ブロガーが上記のコードを使用したとき、彼はMetaObjectクラスに困惑しました。 GetValue()メソッドを介してプロキシ化されているオブジェクトのすべての関連するプロパティを直接取得できます。ソースコードに従って詳細を確認できます
MetaObject#forObject()
すべてのプロキシオブジェクトは、この静的方法を介して入力します
public static metaobject forobject(object object、objectfactory factory、objectwrapperfactory objectwrapperfactory){if(object == null){return systemmetaobject.null_meta_object; } else {return new MetaObject(object、objectFactory、objectWrapperFactory); }}私たちはコンストラクターを直接観察することができます、ここに謎があります
Private MetaObject(Object Object、ObjectFactory ObjectFactory、ObjectWrapperFactory ObjectWrapperFactory){this.originalObject = object; this.objectFactory = objectFactory; this.objectWrapperFactory = objectWrapperFactory; //すべての属性の取得は、ObjectWrapperクラスを通じて取得されます。ここでは、主に(Object instanceof objectWrapper){this.objectWrapper =(objectWrapper)objectをプロキシ化されたオブジェクトオブジェクトタイプを判断します。 } else if(objectWrapperFactory.hasWrapperfor(object)){this.objectwrapper = objectwrapperfactory.getWrapperfor(this、object); } else if(object instanceof map){this.objectwrapper = new MapWrapper(this、(map)object); } else if(object instanceof collection){this.objectwrapper = new CollectionWrapper(this、(collection)object); } else {//頻繁に使用するのは、beanwrapper this.objectwrapper = new beanwrapper(this、object); }}より多くの浸透を理解するために、私たちはフォローアップを続け、最後にそれがリフレクタークラスのコンストラクター関数を呼び出すことを学びました
プライベートリフレクター(class <?> clazz){type = clazz; //コンストラクタークラスAddDefaultConstructor(Clazz)を取得します。 // getメソッドを取得しますaddgetMethods(clazz); //設定されたメソッドを取得しますaddsetMethods(clazz); //内部プロパティセットAddFields(Clazz)を取得します。 ReadablePropertynames = getMethods.Keyset()。toArray(new String [getMethods.KeySet()。size()]); writeablepropertynames = setMethods.keyset()。toarray(new String [setMethods.KeySet()。size()]); for(string propname:readablepropertynames){caseinsensitivePropertymap.put(propname.touppercase(locale.english)、propname); } for(string propname:writeablepropertynames){caseinsensitivePropertymap.put(propname.touppercase(locale.english)、propname); }}このことから、Reflector ProxyクラスとMetaObjectを使用すると、プロキシクラスに関連付けられたすべての属性を通過できることがわかります。例として、 RoutingStatementHandlerクラスを使用してください。上記の操作の後、Delegate configuration/objectFactory/typeHandlerRegistry/resultSetHandler/parameterHandler/mappedStatementおよびその他の属性の内部属性デリゲートと内部属性にアクセスできます。
MetaObject#getValue()
上記では、プロキシクラスの内部プロパティをプロキシする方法を説明しています。また、それを正しく呼ぶ方法を簡単に見ることができます。
public Object getValue(string name){// PropertyTokenizerはStringTokenizerに似ていますが、前者はDelimiter PropertyTokenizer Prop = new PropertyTokenizer(name)として書かれています。 if(prop.hasnext()){metaobject metavalue = metaobjectforproperty(prop.getIndexedname()); if(metavalue == systemmetaobject.null_meta_object){return null; } else {return metavalue.getValue(prop.getChildren()); }} else {return objectwrapper.get(prop); }}ここでは、特定の分析については説明しません。 StatementHandlerが所有するSQL文字列を取得する方法getValue("delegate.boundSql.sql")で取得でき、その中の属性は内部属性(ケースに敏感)でなければなりません。
MetaObject#setValue()
原則はMetaObject#getValue()メソッドと同じです
要約します
上記は、編集者が紹介したSpring MyBatisページングプラグインの使用に関するチュートリアルです。それがあなたに役立つことを願っています。ご質問がある場合は、メッセージを残してください。編集者は時間内に返信します。 wulin.comのウェブサイトへのご支援ありがとうございます!