Point d'entrée de pagination mybatis
Il y a un concept de plugins (plugins) dans Mybatis, qui est essentiellement une idée interceptrice. L'analyse spécifique peut être trouvée dans la recherche sur le principe de Mybatis Interceptor dans un autre article. Sur cette base, cet article affichera directement le code d'implémentation du projet réel et d'autres analyses connexes.
Paging Implémentation de code spécifique
Nous pouvons d'abord définir la classe abstraite du dialect pour implémenter la pagination abstractdialect.java
classe abstraite de la classe abstraite AbstractDialect {/ ** * Si la limite et le décalage sont pris en charge * @return * / public abstract boolean supportLimitoffset (); / ** * Si limite est prise en charge * @return * / public abstract boolean supportLimit (); / ** * Obtenez SQL après avoir ajouté des attributs de pagination * @param sql * @param offset * @param limit * @return * / public abstract String getlimitstring (String SQL, int offset, int limit);}De plus, nous implémenterons séparément la technologie de pagination de pages d'Oracle et MySQL.
MySqldialect.Java-Mysql Pagination Dialecte
La classe publique MySqLDialect étend 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 + "," + limit; } else {return sql + "limit" + limit; }}}Implémentation du dialecte oracedialect.java-oracle
La classe publique Oracledialect étend 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 où rownum <=") .append (start + limite); pagesql.append (") where row_id>") .append (start); return pagesql.toString (); }}L'implémentation d'interceptor du plug-in MyBatis correspondante est la suivante: Intercept instructionHandler # prépare (Connection Con) pour créer la méthode de l'objet de l'instruction SQL
Paginationinterceptor.java
@Intercepts ({@Signature (Type = StatementHandler.class, méthode = "prépare", args = {connection.class})}) public final class PaginationInterceptor implémente interceptor {private final static logger log = loggerFactory .getLogger (paginationInterceptor.class); dialecte adialect privé; public void setDialect (dialect dialect) {this.dialect = dialect; } @Override Public Object Intercept (Invocation Invocation) lève Throwsable {// Obtient directement l'objet intercepté, qui implémente la classe RoutingStationHandler StatementHandler StatementHandler = (StatementHandler) invocation .getTarget (); Boundsql boundsql = instructionHandler.getBoundSQL (); // Obtenez MetaObject, principalement utilisé pour obtenir l'objet et les attributs associés à StatementHandler metaObject MetastatementHandler = metaObject.ForObject (instructionHandler, new defaultObjectFactory (), new defaultObjectWrapperFactory ()); MaptedStatement MapStStmt = (MaptedStatement) MetastatementHandler .GetValue ("Delegate.MaptStatement" .intern ()); // Paginate uniquement la méthode querypagination () if (maptedStmt.getId (). Indexof ("querypagination") == - 1) {return invocation.proceed (); } // Reconstruire le paginateur SQL String OriginalSQL = (String) MetaStationHandler .GetValue ("Delegate.Boundsql.Sql" .Intern ()); MetaStationHandler.SetValue ("Delegate.boundsql.sql" .intern (), dialect .getLimitstring (OriginalSQL, Rowbounds.getoffset (), Rowbounds.getLimit ())); MetaStationHandler.SetValue ("Delegate.Rowbounds.offset" .intern (), rowbounds.no_row_offset); MetaStationHandler.SetValue ("Delegate.Rowbounds.limit" .intern (), rowbounds.no_row_limit); log.debug ("page sql:" + boundsql.getsql ()); retour invocation.proceed (); } // Intercept object @Override public Object Plugin (objet Target) {return plugin.wrap (Target, This); } @Override public void setProperties (Propriétés Propriétés) {}}La configuration XML correspondante du ressort peut être la suivante, en prenant une pagination oracle comme exemple
<! - Configuration du dialect oracle, utilisée pour la pagination oracle -> <bean id = "PaginationInterceptor"> <propriété name = "dialect"> <bean /> </ propriété> </ bean>
Utilisez le code et la configuration ci-dessus pour terminer l'opération de pagination de la base de données Oracle et de la base de données MySQL. Et le blogueur analyse l'un des points
MyBatis # Analyse des objets MetaObject-Metadata
Lorsque le blogueur a utilisé le code ci-dessus, il a été perplexe par la classe MetaObject. Il peut obtenir directement toutes les propriétés associées de l'objet proxyé via la méthode getValue (). Nous pouvons suivre le code source pour en savoir plus
MetaObject#forObject()
Tous les objets proxy entrent par cette méthode statique
public static metaObject ForObject (objet objet, objectFactory objectFactory, objectwrapperfactory objectWrapperFactory) {if (object == null) {return systemMetaObject.null_meta_Object; } else {return new MetaObject (objet, objectFactory, objectWrapperFactory); }}Nous pouvons observer directement le constructeur, voici le mystère
MetaObject privé (objet Object, objectFactory ObjectFactory, objectWrapperFactory ObjectWrapperFactory) {this.originalObject = objet; this.ObjectFactory = objectFactory; this.objectwrapperfactory = objectWrapperFactory; // Toutes les acquisitions d'attribut sont obtenues via la classe ObjectWrapper. Ici, nous jugeons principalement le type d'objet objet qui est proxyé if (objet instance Of ObjectWrapper) {this.objectwrapper = (objectWrapper) objet; } else if (objectwrapperfactory.haswrapperfor (objet)) {this.objectwrapper = objectWrapperFactory.getWrapperFor (this, object); } else if (objet instanceof map) {this.objectwrapper = new MapWrapper (this, (map) objet); } else if (objet instanceOf Collection) {this.objectwrapper = new CollectionWrapper (this, (collection) object); } else {// Ce que nous utilisons souvent, c'est beanwrapper this.objectwrapper = new BeanWrapper (this, objet); }}Pour comprendre plus d'infiltrat, nous continuons à suivre, et finalement nous avons appris qu'il appellera la fonction du constructeur de la classe de réflecteur
Réflecteur privé (classe <?> Clazz) {type = Clazz; // Obtenez la classe de constructeur adddefaultConstructor (Clazz); // Obtenez la méthode Get Set AddGetMethods (Clazz); // Obtenez la méthode définie AddSetMethods (Clazz); Clazz); // Obtenez le jeu de propriétés interne Addfields (Clazz); lisiblepropertyNames = getMethods.KeySet (). ToArray (new String [getMethods.KeySet (). size ()]); WriteablePropertyNames = setMethods.KeySet (). ToArray (new String [setMethods.KeySet (). size ()]); for (String propName: liteableProperTyNames) {CaseInSensitiveProperTyMap.put (propName.ToupperCase (Locale.English), propname); } pour (String propName: WriteableProperTyNames) {CaseInSensitiveProperTyMap.put (propName.ToupperCase (Locale.English), propname); }} À partir de cela, nous pouvons savoir qu'à l'aide de la classe de proxy du réflecteur et du métaobject, vous pouvez traverser tous les attributs associés à la classe de proxy. Prenez RoutingStatementHandler à titre d'exemple. Après l'opération ci-dessus, vous pouvez accéder au délégué d'attribut interne et aux attributs internes du délégué configuration/objectFactory/typeHandlerRegistry/resultSetHandler/parameterHandler/mappedStatement et autres attributs.
MetaObject#getValue()
Ce qui précède explique comment proxyer les propriétés internes de la classe de procuration. Nous pouvons également jeter un bref aperçu de la façon de l'appeler correctement.
Objet public getValue (nom de chaîne) {// PropertyTokenizer est similaire à StringTokenizer, sauf que le premier est écrit en tant que délimiter PropertyTokenizer prop = new PropertyTokenizer (nom); 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); }} L'analyse spécifique ne sera pas expliquée ici. Comment obtenir la chaîne SQL appartenant à StatementHandler peut être obtenue par getValue("delegate.boundSql.sql") et les attributs doivent être des attributs internes (sensible à la caisse).
MetaObject#setValue()
Le principe est le même que MetaObject#getValue()
Résumer
Ce qui précède est le tutoriel sur l'utilisation du plug-in Spring MyBatis Paging vous a présenté par l'éditeur. J'espère que cela vous sera utile. Si vous avez des questions, veuillez me laisser un message et l'éditeur vous répondra à temps. Merci beaucoup pour votre soutien au site Web Wulin.com!