Selon l'idée de la page suivante, il est facile d'implémenter la conception multi-locataire de MyBitas.
Utilisez l'intercepteur fourni par Mybatis. Les instructions PAGED SQL sont traitées en différents SQL paginaires par encapsulation.
Cet exemple a implémenté la fonction de pagination de MySQL et Oracle. Faites attention au package de devis suivant et ne le citez pas incorrectement.
import java.sql.connection; import java.sql.preparedstatement; importer java.sql.resultSet; import java.sql.sqlexception; importer java.util.list; import java.util.properties; import org.apache.ibatis.executor.prometer.prometerhandler; org.apache.ibatis.executor.statement.routingstationhandler; import org.apache.ibatis.executor.statement.statementhandler; import org.apache.ibatis.mapping.boundsql; import org.apache.ibatis.mapping.maptStatement; import org.apache.ibatis.mapping.pamesperter; Import Org.apache.ibatis.mapping.pamespert. 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; / ** * * intercepteur de pagination, utilisé pour intercepter les opérations qui nécessitent une requête de pagination et ensuite les pagininer. * Le principe de la pagine MyBatis est implémenté à l'aide d'intercepteurs: * Pour utiliser JDBC pour fonctionner dans la base de données, vous devez avoir un objet d'instruction correspondant. Avant que MyBatis exécute l'instruction SQL, il générera un objet d'instruction contenant l'instruction SQL, et l'instruction SQL correspondante * est générée avant l'instruction, afin que nous puissions commencer par l'instruction SQL utilisée pour générer l'instruction avant de générer l'instruction. Dans l'instruction MyBatis, l'instruction est générée par la méthode * Préparez-vous de l'objet RoutingStationHandler. Par conséquent, l'une des idées d'utilisation d'un intercepteur pour implémenter le paginage MyBatis consiste à intercepter la méthode de préparation de l'interface de relevéhandleur, puis à modifier l'instruction SQL en l'instruction SQL de requête de pagination correspondante dans la méthode interceptor, puis à appeler la méthode de préparation de l'objet * instructionhandler, c'est-à-dire à l'appel invocation.proceed (). * Pour la pagination, l'une des opérations que nous devons effectuer dans l'intercepteur est de compter le nombre total d'enregistrements qui remplissent les conditions actuelles. C'est en obtenant l'instruction SQL d'origine, en le modifiant en instruction statistique correspondante, puis en remplaçant les paramètres dans l'instruction SQL à l'aide des paramètres encapsulés MyBatis et des paramètres de réglage *. Ensuite, l'instruction SQL interrogeant le nombre d'enregistrements est exécutée pour compter le nombre total d'enregistrements. * * / @Intercepts ({@ signature (type = instructionHandler.class, méthode = "prépare", args = {connection.class})}) classe publique PageInterceptor implémente interceptor {private String dialect = ""; // Database Dialect Private String pagesqlid = ""; // ID qui doit être intercepté dans MAPPER.xml (correspondance régulière) Intercept de l'objet public (invocation invocation) lance Throwsable {// Il n'y a en fait que deux classes d'implémentation pour StatementHandler, l'une est RoutingStatementHandler, et l'autre est la classe abstraite BasestationHandler. // BaseStatementHandler a trois sous-classes, à savoir SimplestationHandler, préparéStatementHandler et callableStatementHandler. // SimplestatementHandler est utilisé pour traiter les déclarations, préparéStationHandler gère PreadStatement et CallableStatementHandler est // traite callableStatement. MyBatis crée un routingStatementHandler lors du traitement des instructions SQL. Dans RoutingStatementHandler, il existe une propriété déléguée de // Type de relevé. Le routingStatementHandler créera un BaseStatementHandler correspondant en fonction des différentes instructions, c'est-à-dire SimplestationHandler, // préparéStationHandler ou callableStatementHandler. Dans le RoutingStatementHandler, toutes les méthodes d'interface de déclaration de déclaration sont implémentées par le délégué correspondant au délégué appelé. // Nous avons marqué l'interceptor intercepte uniquement la méthode de préparation de l'interface de déclaration de déclaration avec @Signature sur la classe PageInterceptor. Parce que MyBatis ne l'enroule que via la méthode du plugin Interceptor lors de l'établissement de RoutingStatementHandler, donc l'objet cible que nous interceptons ici doit être l'objet RoutingStationmentHandler. if (invocation.getTarget () instanceof routingstatementHandler) {routingStAttementHandler StatementHandler = (routingStatementHandler) invocation.getTTarget (); StatementHandler Delegate = (StatementHandler) Reflecthelper.getFieldValue (StatementHandler, "Delegate"); Boundsql boundsql = delegate.getBoundsql (); Objet obj = boundsql.getParameterObject (); if (obj instanceof page <?>) {page <?> page = (page <?>) obj; // Récupère la propriété MaptedStatement du BasestationHandler de la classe parent du délégué mappédstatement mappedStatement = (maptedstatement) reflecthelper.getfieldvalue (délégué, "maptedstatement"); // Le paramètre de la méthode de préparation interceptée est une connexion d'objet de connexion Connexion = (connexion) invocation.getArgs () [0]; // Obtenez l'instruction SQL actuellement exécutée, c'est-à-dire l'instruction SQL que nous écrivons directement dans la chaîne d'instruction de mappage de mappeur SQL = BOUNDSQL.getsql (); // Définissez le nombre total d'enregistrements pour l'objet de paramètre de page actuel this.setTotalRecord (page, maptedstatement, connexion); // Obtenez la chaîne de instruction SQL PAGE PAGSQL = this.getPagesQL (page, SQL); // Utilisez la réflexion pour définir l'attribut SQL correspondant à l'actuel BoundsQL pour créer une bonne instruction SQL Paged pour US Reflecthelper.SetFieldValue (BOUNDSQL, "SQL", PageSQL); }} return invocation.proceed (); } / ** * Définissez le nombre total d'enregistrements pour la page d'objet du paramètre actuel * * @param Page Mappe Mapping Instruction * @param MAPPEDSATAMENT MAPTER MAPPING GAPPING * @Param Connection Connexion de la base de données * / Private void SettotalRecord (Page <?> Page, MapedStatement MAPPAMENT, connexion de connexion) {// Obtenir la correspondance BoundsQL. Ce BoundsQL est en fait le même objet que le BoundsQL que nous avons obtenu à l'aide de StatementHandler. // Le délégué BoundsQL est également obtenu via la méthode mapsstatement.getBoundSQL (paramobj). BOUNDSQL BOURNSQL = MAPPEDSATATION.GETBOUNDSQL (PAGE); // Obtenez la chaîne d'instruction SQL correspondante sql = boundsql.getsql (); // obtient l'instruction SQL correspondante qui calcule le nombre total d'enregistrements en interrogeant la chaîne d'instruction SQL CountSQL = this.getCountsql (SQL); // Obtenez la carte des paramètres correspondante via BOUNDSQL LIST <AMATERMAPPORD> ParameTermAppings = Boundsql.GetParameTermAppings (); // Utilisez la configuration, le compte de l'instruction SQL pour interroger les enregistrements, les paramètres de la relation de mappage des paramètres et la page d'objet de paramètre pour créer un objet BoundsQL correspondant aux enregistrements de requête. BOUNDSQL COUNTBOUNDSQL = NOUVEAU BOURNSQL (MAPPEDSATATION.GETCONFIGURATION (), COUNTSQL, ParameTermAppings, page); // Créez un objet de paramètre Handleur pour définir les paramètres via MaptedStatement, Page d'objet de paramètre et BoundsQL Object CountBoundSQL. ParameterHandler ParameterHandler = new defaultParameterHandler (maptedstatement, page, countBoundSQL); // Créez un objet PreadStatement correspondant à CountSQL via la connexion. Préparé Pstmt = null; ResultSet rs = null; try {pstmt = connection.preparestatement (countSQL); // Définir les paramètres de paramètre Handleur pour l'objet PreadStatement via ParametHandler.SetParameters (PSTMT); // Ensuite, il est exécuté pour obtenir le nombre total d'enregistrements et obtenir les résultats. rs = pstmt.ExecuteQuery (); if (Rs.Next ()) {int totalRecord = Rs.GetInt (1); // Définit le nombre total d'enregistrements pour la page de paramètre actuelle objet.SetTotalRecord (totalRecord); }} catch (sqlexception e) {e.printStackTrace (); } enfin {try {if (rs! = null) Rs.close (); if (pstmt! = null) pstmt.close (); } catch (sqlexception e) {e.printStackTrace (); }}} / ** * Instruction SQL qui obtient le nombre total d'enregistrements correspondant dans la requête * @param sql * @return * / private string getCountsql (String sql) {int index = sql.indexof ("from"); return "select count (*)" + sql.substring (index); } / ** * Obtenez l'instruction SQL de requête de pagination correspondante basée sur l'objet page. Seuls deux types de bases de données sont fabriqués ici, MySQL et Oracle * Aucune autre base de données ne fait paginer * * @param Page Paging Object * @param SQL Original SQL Instruction * @return * / private String getPagesql (page <?> Page, String SQL) {StringBuffer sqlBuffer = new StringBuffer (SQL); if ("mysql" .equalsignorecase (dialect)) {return getmysqlpagesql (page, sqlbuffer); } else if ("Oracle" .EqualsIgnoreCase (dialect)) {return getoraclePagesQl (page, sqlbuffer); } return sqlbuffer.toString (); } / ** * Obtenez l'instruction de requête Paged pour la base de données MySQL * @Param Page Paging Object * @Param SQLBuffer StringBuffer Contient l'instruction SQL d'origine * @return MySQL DATABASE PAGING GAGING * PRIVATE String GetMysQlpagesql (Page <?> Page, StringBuffer SqlBuffer) {// Calculater la position de la position du premier record. La position de l'enregistrement dans MySQL commence à partir de 0. // System.out.println ("page:" + page.getPage () + "--------" + page.getRows ()); int offset = (page.getPage () - 1) * page.getRows (); sqlbuffer.append ("limite") .append (offset) .append (","). APPEND (page.getRows ()); return sqlbuffer.toString (); } / ** * Obtenez l'instruction de requête paginaire pour Oracle Database * @param Page Paging Object * @param SQLBuffer StringBuffer objet contenant l'instruction SQL d'origine * @return Pagination Instruction Query pour Oracle Database * / Private String GetoraclePagesQL (Page <?> Page, StringBuffer SqlBuffer) {// Calculate du localisation de l'emplacement de l'emplacement. La pagination oracle est effectuée via Rownum, et Rownum commence à partir de 1 int offset = (page.getPage () - 1) * page.getRows () + 1; sqlbuffer.insert (0, "SELECT U. sqlbuffer.insert (0, "select * from (") .append (") où r> =") .append (offset); // L'instruction SQL ci-dessus ressemble à ceci: // select * FROM (SELECT U }! } else {return arg0; }} / ** * Définissez les propriétés définies lors de l'enregistrement de l'interceptor * / public void setProperties (Propriétés P) {} public String getDialect () {return dialect; } public void setDialect (chaîne dialect) {this.dialect = dialect; } public String getPagesqlid () {return pagesqlid; } public void setPagesQLid (String pagesqlid) {this.pagesqlid = pagesqlid; }} Configuration XML:
<! - Configuration de programmation d'interface MyBatis -> <an Bean> <! - BasEpackage spécifie le package à analyser. Les mappeurs sous ce package seront recherchés. Plusieurs packages peuvent être spécifiés, séparés par des virgules ou des demi-finales -> <propriété name = "basepackage" value = "com.yidao.mybatis.dao" /> <propriété name = "SqlSessionFactoryBeAnname" Value = "SqlSessionFactory" /> </Ean> <! name = "dialect" value = "mysql" /> <! - Intercepter l'instruction avec des caractères de requête contenant l'ID dans le fichier MAPPER.xml -> <propriété name = "pagesqlid" value = ". * Query $" /> </ bean>
Classe de page
package com.yidao.utils; / ** Regardez-le vous-même, quels champs sont nécessaires pour y ajouter * / Page de classe publique {lignes entières privées; Page entière privée = 1; entier privé totalRecord; public entier getrows () {return lignes; } public void setRows (Integer Rows) {this.Rows = lignes; } public Integer getPage () {return page; } public void setPage (page entier) {this.page = page; } public entier getTotalRecord () {return totalRecord; } public void SettotalRecord (entier totalRecord) {this.totalRecord = totalRecord; }} Classe de réflecthelper
package com.yidao.utils; import java.lang.reflect.field; import org.apache.commons.lang3.reflect.fieldutils; public class reflecthelper {public static objet getFieldValue (objet obj, chaîne fieldname) {if (obj == null) {return null; } Field cibleField = getTargetField (obj.getClass (), fieldName); try {return fieldUtils.readField (TargetField, obj, true); } catch (illégalaccessException e) {e.printStackTrace (); } return null; } Field statique public getTargetField (class <?> TargetClass, String fieldName) {field field = null; try {if (cibleClass == null) {return field; } if (object.class.equals (cibleClass)) {return field; } field = fieldUtils.getDeclaredField (TargetClass, fieldName, true); if (field == null) {field = getTargetField (cibleClass.getsuperclass (), fieldName); }} catch (exception e) {} champ de retour; } public static void setFieldValue (objet obj, chaîne fieldname, valeur objet) {if (null == obj) {return;} field cibleField = getTargetField (obj.getClass (), fieldname); try {FieldUtils.WriteField (TargetField, Obj, Value); } catch (illégalaccessException e) {e.printStackTrace (); }}}Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.