Heim Java javaLernprogramm Ausführliche Erläuterung der Verbesserungen beim Caching und der Cache-Nutzung im MyBatis-Framework von Java

Ausführliche Erläuterung der Verbesserungen beim Caching und der Cache-Nutzung im MyBatis-Framework von Java

Jan 23, 2017 am 09:29 AM

Level 1 Cache und Level 2 Cache
MyBatis gestaltet den Datencache in einer zweistufigen Struktur, unterteilt in Level 1 Cache und Level 2 Cache:
Level 1 Cache ist ein Cache auf Sitzungsebene, der sich in befindet die primäre Datenbank. Das SqlSession-Objekt der Sitzung wird auch als lokaler Cache bezeichnet. Der First-Level-Cache ist eine intern von MyBatis implementierte Funktion. Er kann nicht von Benutzern konfiguriert werden. Er wird standardmäßig automatisch unterstützt und Benutzer haben nicht das Recht, ihn anzupassen (dies gilt jedoch nicht unbedingt). Er kann durch die Entwicklung eines Plug-Ins geändert werden -ins);
Der Cache der zweiten Ebene ist ein Cache auf Anwendungsebene. Er hat einen langen Lebenszyklus, der dem Deklarationszyklus der Anwendung entspricht.
Die Organisation des Caches der ersten Ebene und des Caches der zweiten Ebene in MyBatis ist wie folgt:

Ausführliche Erläuterung der Verbesserungen beim Caching und der Cache-Nutzung im MyBatis-Framework von Java

Der Arbeitsmechanismus des Caches der ersten Ebene:
Der Cache der ersten Ebene ist die Sitzungsebene. Im Allgemeinen verwendet ein SqlSession-Objekt ein Executor-Objekt, um Sitzungsvorgänge abzuschließen, und das Executor-Objekt verwaltet einen Cache-Cache, um die Abfrageleistung zu verbessern.
Der Arbeitsmechanismus des Caches der zweiten Ebene:
Wie oben erwähnt, verwendet ein SqlSession-Objekt ein Executor-Objekt, um den Sitzungsvorgang abzuschließen. Der Schlüssel zum Cache-Mechanismus der zweiten Ebene von MyBatis besteht darin, viel Aufhebens zu machen über dieses Executor-Objekt. Wenn der Benutzer „cacheEnabled=true“ konfiguriert, fügt MyBatis beim Erstellen eines Executor-Objekts für das SqlSession-Objekt einen Dekorator zum Executor-Objekt hinzu: CachingExecutor. Zu diesem Zeitpunkt verwendet SqlSession das CachingExecutor-Objekt, um die Vorgangsanforderung abzuschließen. Bei einer Abfrageanforderung ermittelt CachingExecutor zunächst, ob die Abfrageanforderung ein zwischengespeichertes Ergebnis im sekundären Cache auf Anwendungsebene hat. Wenn ein Abfrageergebnis vorhanden ist, wird das zwischengespeicherte Ergebnis direkt zurückgegeben Wird an das reale Executor-Objekt übergeben, um die Abfrage abzuschließen. Nach dem Vorgang legt CachingExecutor die vom realen Executor zurückgegebenen Abfrageergebnisse im Cache ab und gibt sie dann an den Benutzer zurück.
Der Cache der zweiten Ebene von MyBatis ist flexibler gestaltet. Sie können den Cache auch anpassen, indem Sie die Schnittstelle org.apache.ibatis.cache.Cache implementieren Verwenden Sie Speicher-Caching-Bibliotheken von Drittanbietern wie Memcached usw.

Ausführliche Erläuterung der Verbesserungen beim Caching und der Cache-Nutzung im MyBatis-Framework von Java

Ausführliche Erläuterung der Verbesserungen beim Caching und der Cache-Nutzung im MyBatis-Framework von Java

Cache-Transformation
Problem:
Das häufigste Problem ist, dass nach dem Einschalten des Caches, egal ob Die Abfrage erfolgt im Paging. Welche Seite auch immer die Daten der ersten Seite zurückgibt. Darüber hinaus haben die übergebenen Parameter keine Auswirkung, wenn das SQL-Plugin zur automatischen Generierung zum Generieren der SQL der get-Methode verwendet wird. Unabhängig davon, wie viele Parameter übergeben werden, wird das Abfrageergebnis des ersten Parameters zurückgegeben.

Warum treten diese Probleme auf:
Als ich zuvor den Ausführungsprozess von Mybatis erläuterte, erwähnte ich, dass der Executor von Mybatis beim Einschalten des Caches zuerst die Daten aus dem Cache liest die abzufragende Datenbank. Das Problem liegt hier. Der Ausführungszeitpunkt des Plug-Ins für die automatische SQL-Generierung und des Paging-Plugins liegt im Anweisungshandler, und der Anweisungshandler wird nach dem Executor ausgeführt. in werden durch Umschreiben von SQL implementiert. Beim Lesen des Cache-Schlüssels (der Schlüssel besteht aus SQL und entsprechenden Parameterwerten) wird das ursprüngliche SQL verwendet, daher wird es natürlich ein Problem geben.

Lösen Sie das Problem:
Sobald Sie die Ursache des Problems gefunden haben, wird es einfacher, es zu lösen. Schreiben Sie einfach die Schlüsselgenerierungsmethode im Executor über den Interceptor neu und verwenden Sie automatisch generiertes SQL (entsprechend dem SQL-Plug-In für die automatische Generierung) oder fügen Sie Paging-Informationen (entsprechend dem Paging-Plug-In) hinzu, wenn die Generierung möglich ist.

Interceptor-Signatur:

@Intercepts({@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
public class CacheInterceptor implements Interceptor {
...
}
Nach dem Login kopieren

Wie aus der Signatur ersichtlich ist, ist der abzufangende Zieltyp Executor (Hinweis: Der Typ kann nur als konfiguriert werden Schnittstellentyp), die abgefangene Methode ist die Methode namens query.

Intercept-Implementierung:

public Object intercept(Invocation invocation) throws Throwable {
    Executor executorProxy = (Executor) invocation.getTarget();
    MetaObject metaExecutor = MetaObject.forObject(executorProxy, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
    // 分离代理对象链
    while (metaExecutor.hasGetter("h")) {
      Object object = metaExecutor.getValue("h");
      metaExecutor = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
    }
    // 分离最后一个代理对象的目标类
    while (metaExecutor.hasGetter("target")) {
      Object object = metaExecutor.getValue("target");
      metaExecutor = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
    }
    Object[] args = invocation.getArgs();
    return this.query(metaExecutor, args);
  }
  
  public <E> List<E> query(MetaObject metaExecutor, Object[] args) throws SQLException {
    MappedStatement ms = (MappedStatement) args[0];
    Object parameterObject = args[1];
    RowBounds rowBounds = (RowBounds) args[2];
    ResultHandler resultHandler = (ResultHandler) args[3];
    BoundSql boundSql = ms.getBoundSql(parameterObject);
    // 改写key的生成
    CacheKey cacheKey = createCacheKey(ms, parameterObject, rowBounds, boundSql);
    Executor executor = (Executor) metaExecutor.getOriginalObject();
    return executor.query(ms, parameterObject, rowBounds, resultHandler, cacheKey, boundSql);
  }
  
  private CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
    Configuration configuration = ms.getConfiguration();
    pageSqlId = configuration.getVariables().getProperty("pageSqlId");
    if (null == pageSqlId || "".equals(pageSqlId)) {
      logger.warn("Property pageSqlId is not setted,use default &#39;.*Page$&#39; ");
      pageSqlId = defaultPageSqlId;
    }
    CacheKey cacheKey = new CacheKey();
    cacheKey.update(ms.getId());
    cacheKey.update(rowBounds.getOffset());
    cacheKey.update(rowBounds.getLimit());
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    // 解决自动生成SQL,SQL语句为空导致key生成错误的bug
    if (null == boundSql.getSql() || "".equals(boundSql.getSql())) {
      String id = ms.getId();
      id = id.substring(id.lastIndexOf(".") + 1);
      String newSql = null;
      try {
        if ("select".equals(id)) {
          newSql = SqlBuilder.buildSelectSql(parameterObject);
        }
        SqlSource sqlSource = buildSqlSource(configuration, newSql, parameterObject.getClass());
        parameterMappings = sqlSource.getBoundSql(parameterObject).getParameterMappings();
        cacheKey.update(newSql);
      } catch (Exception e) {
        logger.error("Update cacheKey error.", e);
      }
    } else {
      cacheKey.update(boundSql.getSql());
    }
  
    MetaObject metaObject = MetaObject.forObject(parameterObject, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
  
    if (parameterMappings.size() > 0 && parameterObject != null) {
      TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
      if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
        cacheKey.update(parameterObject);
      } else {
        for (ParameterMapping parameterMapping : parameterMappings) {
          String propertyName = parameterMapping.getProperty();
          if (metaObject.hasGetter(propertyName)) {
            cacheKey.update(metaObject.getValue(propertyName));
          } else if (boundSql.hasAdditionalParameter(propertyName)) {
            cacheKey.update(boundSql.getAdditionalParameter(propertyName));
          }
        }
      }
    }
    // 当需要分页查询时,将page参数里的当前页和每页数加到cachekey里
    if (ms.getId().matches(pageSqlId) && metaObject.hasGetter("page")) {
      PageParameter page = (PageParameter) metaObject.getValue("page");
      if (null != page) {
        cacheKey.update(page.getCurrentPage());
        cacheKey.update(page.getPageSize());
      }
    }
    return cacheKey;
}
Nach dem Login kopieren

Plugin-Implementierung:

public Object plugin(Object target) {
  // 当目标类是CachingExecutor类型时,才包装目标类,否者直接返回目标本身,减少目标被代理的
  // 次数
  if (target instanceof CachingExecutor) {
    return Plugin.wrap(target, this);
  } else {
    return target;
  }
}
Nach dem Login kopieren

Ausführlichere Erklärung der MyBatis For-Artikel von Java Im Zusammenhang mit Cache- und Cache-Nutzungsverbesserungen im Framework achten Sie bitte auf die chinesische PHP-Website!


Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
2 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
Repo: Wie man Teamkollegen wiederbelebt
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Abenteuer: Wie man riesige Samen bekommt
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Top 4 JavaScript -Frameworks in 2025: React, Angular, Vue, Svelte Top 4 JavaScript -Frameworks in 2025: React, Angular, Vue, Svelte Mar 07, 2025 pm 06:09 PM

Dieser Artikel analysiert 2025 die vier besten JavaScript -Frameworks (React, Angular, Vue, Svelte) und verglichen ihre Leistung, Skalierbarkeit und Zukunftsaussichten. Während alle aufgrund starker Gemeinschaften und Ökosysteme dominant bleiben, sind ihr relatives Popul

Wie implementiere ich mehrstufige Caching in Java-Anwendungen mit Bibliotheken wie Koffein oder Guava-Cache? Wie implementiere ich mehrstufige Caching in Java-Anwendungen mit Bibliotheken wie Koffein oder Guava-Cache? Mar 17, 2025 pm 05:44 PM

In dem Artikel wird in der Implementierung von mehrstufigem Caching in Java mithilfe von Koffein- und Guava-Cache zur Verbesserung der Anwendungsleistung erläutert. Es deckt die Einrichtungs-, Integrations- und Leistungsvorteile sowie die Bestrafung des Konfigurations- und Räumungsrichtlinienmanagements ab

Node.js 20: wichtige Leistungssteigerung und neue Funktionen Node.js 20: wichtige Leistungssteigerung und neue Funktionen Mar 07, 2025 pm 06:12 PM

Node.js 20 verbessert die Leistung durch V8 -Motorverbesserungen erheblich, insbesondere durch schnellere Müllsammlung und E/A. Zu den neuen Funktionen gehören eine bessere Support von WebAssembly und raffinierte Debugging -Tools, die Produktivität der Entwickler und die Anwendungsgeschwindigkeit.

Wie funktioniert der Klassenladungsmechanismus von Java, einschließlich verschiedener Klassenloader und deren Delegationsmodelle? Wie funktioniert der Klassenladungsmechanismus von Java, einschließlich verschiedener Klassenloader und deren Delegationsmodelle? Mar 17, 2025 pm 05:35 PM

Mit der Klassenbelastung von Java wird das Laden, Verknüpfen und Initialisieren von Klassen mithilfe eines hierarchischen Systems mit Bootstrap-, Erweiterungs- und Anwendungsklassenloadern umfasst. Das übergeordnete Delegationsmodell stellt sicher

Spring Boot Snakeyaml 2.0 CVE-2022-1471 Problem behoben Spring Boot Snakeyaml 2.0 CVE-2022-1471 Problem behoben Mar 07, 2025 pm 05:52 PM

Dieser Artikel befasst sich mit der Verwundbarkeit von CVE-2022-1471 in Snakeyaml, einem kritischen Fehler, der die Ausführung von Remote-Code ermöglicht. Es wird beschrieben

ICEBERG: Die Zukunft von Data Lake Tabellen ICEBERG: Die Zukunft von Data Lake Tabellen Mar 07, 2025 pm 06:31 PM

Iceberg, ein offenes Tabellenformat für große analytische Datensätze, verbessert die Leistung und Skalierbarkeit von Data Lake. Es befasst sich mit Einschränkungen von Parquet/ORC durch internes Metadatenmanagement und ermöglicht eine effiziente Schemaentwicklung, Zeitreisen, gleichzeitiger W

Wie kann ich funktionale Programmierungstechniken in Java implementieren? Wie kann ich funktionale Programmierungstechniken in Java implementieren? Mar 11, 2025 pm 05:51 PM

In diesem Artikel wird die Integration der funktionalen Programmierung in Java unter Verwendung von Lambda -Ausdrücken, Streams -API, Methodenreferenzen und optional untersucht. Es zeigt Vorteile wie eine verbesserte Lesbarkeit der Code und die Wartbarkeit durch SUKTIVE UND VERUSNAHMETALITÄT

Wie benutze ich Maven oder Gradle für das fortschrittliche Java -Projektmanagement, die Erstellung von Automatisierung und Abhängigkeitslösung? Wie benutze ich Maven oder Gradle für das fortschrittliche Java -Projektmanagement, die Erstellung von Automatisierung und Abhängigkeitslösung? Mar 17, 2025 pm 05:46 PM

In dem Artikel werden Maven und Gradle für Java -Projektmanagement, Aufbau von Automatisierung und Abhängigkeitslösung erörtert, die ihre Ansätze und Optimierungsstrategien vergleichen.

See all articles