Artikelverzeichnis
- Vorwort
- Projektadresse
- 1. Traditionelle JDBC-Probleme und benutzerdefinierte Framework-Lösungen
- 2. Kundenspezifische Designideen für Persistenzschichten
-
- 2.1 Benutzerseite (Projekt): Führen Sie das JAR-Paket des benutzerdefinierten Persistenzschicht-Frameworks ein
- 2.2 Das benutzerdefinierte Persistenzschicht-Framework selbst (Engineering): Das Wesentliche ist die Kapselung von JDBC
-
- 2.2.1. Lesen Sie die Konfigurationsdatei:
- 2.2.2. Analysieren der Konfigurationsdatei: Ich verwende hier dom4j, aber Sie können auch andere verwenden
- 2.2.3 Erstellen Sie die SqlSessionFactory-Schnittstelle und die Implementierungsklasse DefaultSqlSessionFactory.
- 2.2.4. Executor-Schnittstelle und Implementierungsklasse erstellen SimpleExecutor-Implementierungsklasse, erstellen Sie eine Abfragemethode zum Ausführen von JDBC-Code.
- 3.genericTokenParserzheg-Tag-Parser-Klasse
- 4. Über sqlessionFactoyBuilder, sqlessionFactoy, sqlession.
- 5. Informationen zum Rückgabewert resultType und zum Eingabeparameter paramterType
- 6. Schnittstellenentwicklungsspezifikation in mybatis
- 7. Informationen zum Inhalt des mybatis-Quellcodes
- 8.Mybatis faul laden, was ist das Implementierungsprinzip
- 9. Die drei Arten von Mybatis Executor, der Unterschied zwischen ihnen
- 10. Primärer und sekundärer Cache von Mybatis (verteiltes Caching kann nicht implementiert werden, ein Caching-Framework eines Drittanbieters ist erforderlich)
- 11. Funktionsprinzip des Mybatis-Plug-Ins und Schreiben eines Plug-Ins
Vorwort
Die Ausgabequelle des Artikelinhalts: Lagou Education Java High Salary Training Camp. P7-Kurs
Dieser Artikel ist Teil der Notizen nach der Schule im Lernkurs.
Projektadresse
Projektcode:
Link: https://pan.baidu.com/s/1pdtE7NkQb1SHQo9RnfSOTw
Extraktionscode: sc4m
Code-Cloud-Adresse: https://gitee.com/nie_jian_ming/njm_all_homework/tree/master/%E7%AC%AC%E4%B8%80%E9%98%B6%E6%AE%B5.%E6%A8% A1% E5% 9D% 97% E4% B8% 80.Mybatis% E4% BD% 9C% E4% B8% 9A
1. Traditionelle JDBC-Probleme und benutzerdefinierte Framework-Lösungen
Fragen:
1. Das häufige Erstellen und Freigeben von Datenbankverbindungen führt zur Verschwendung von Systemressourcen und beeinträchtigt somit die Systemleistung.
2. Die SQL-Anweisung, die Parameterübergabe und die Analyseergebnismenge sind alle fest codiert. SQL-Änderungen erfordern eine Änderung des Java-Codes, wodurch die Pflege des Codes schwierig wird.
Lösung:
1. Verwenden Sie den Datenbankverbindungspool, um Verbindungsressourcen zu initialisieren und das Problem des häufigen Erstellens und Freigebens von Datenbankverbindungen zu lösen.
2. Extrahieren Sie SQL-Anweisungen in XML-Konfigurationsdateien, verwenden Sie Reflection, Introspection und andere zugrunde liegende Technologien, um Entitäten und Tabellen automatisch Attributen und Feldern zuzuordnen, Reflection, um Parameter festzulegen, und Introspection, um Ergebnisse zurückzugeben. Set-Paket.
Beteiligte
Entwurfsmuster : Builder-Entwurfsmuster, manuelles Muster (Session Factory), Proxy-Modus (dynamischer JDK-Proxy zum Generieren von Proxy-Objekten für die Dao-Schnittstelle)
2. Kundenspezifische Designideen für Persistenzschichten
2.1 Benutzerseite (Projekt): Führen Sie das JAR-Paket des benutzerdefinierten Persistenzschicht-Frameworks ein
- Geben Sie zwei Teile der Konfigurationsinformationen an: Datenbankkonfigurationsinformationen, SQL-Konfigurationsinformationen (SQL-Anweisung, Parametertyp, Rückgabewerttyp)
- Verwenden Sie die Konfigurationsdatei, um diese beiden Teile der Konfigurationsinformationen
bereitzustellen: 1.sqlMapConfig.xml: Speichern Sie die Datenbankkonfigurationsinformationen, importieren Sie mapper.xml.
2.mapper.xml: Speichern Sie die SQL-Konfigurationsinformationen.
2.2 Das benutzerdefinierte Persistenzschicht-Framework selbst (Engineering): Das Wesentliche ist die Kapselung von JDBC
2.2.1. Lesen Sie die Konfigurationsdatei:
- Erstellen Sie eine Klasse, um die Konfigurationsdatei entsprechend dem Pfad der Konfigurationsdatei in einen Byte-Eingabestream zu laden und im Speicher zu speichern.
Implementierungsschritte : Erstellen einer Klasse Ressourcen, Lademethode: InputSteam getResourceAsSteam (String path)
Die gelesenen Konfigurationsinformationen werden in Form eines Streams im Speicher gespeichert, der nicht einfach zu bedienen ist. Hier werden zwei javaBeans (Containerobjekte) erstellt für objektorientiertes Denken .: Speichern Sie den analysierten Inhalt der Konfigurationsdatei, was auch für den späteren Zugriff praktisch ist.
Implementierungsschritte : Erstellen Sie zwei Konfigurationsklassen
Konfiguration : Kernkonfigurationsklasse: Speichern Sie den von sqlMapConfig.xml analysierten Inhalt, speichern Sie grundlegende Informationen der Datenbank, Map <only ID, Mapper> Eindeutige ID: Namespace + "." + ID
MappedStatement : Mapping Configuration Klasse: Speichern Sie den von mapper.xml analysierten Inhalt, speichern Sie die SQL-Anweisung, den Anweisungstyp, den Java-Typ des Eingabeparameters und den Java-Typ des Ausgabeparameters
2.2.2. Analysieren der Konfigurationsdatei: Ich verwende hier dom4j, aber Sie können auch andere verwenden
Implementierungsschritte:
Erstellen Sie die SqlSessionFactoryBuilder-Klasse und anschließend eine Methode: build (InputSteam in), um die Session Factory zu erstellen.
In der Erstellungsmethode sind zwei Dinge implementiert:
1. Verwenden Sie dom4j, um die Konfigurationsdatei zu analysieren und den analysierten Inhalt in ein Containerobjekt zu kapseln.
2. Erstellen Sie ein SqlSessionFactory-Objekt (Factory-Modus) und erstellen Sie ein sqlSession-Sitzungsobjekt
2.2.3 Erstellen Sie die SqlSessionFactory-Schnittstelle und die Implementierungsklasse DefaultSqlSessionFactory.
Erstellen Sie dann die SqlSessionFactory-Schnittstelle und die Implementierungsklasse DefaultSqlSessionFactory basierend auf dem Öffnungs- und Schließprinzip. Schreiben Sie eine Methode zum Erstellen von sqlSession.
Methode: openSession () //
Abrufen des Instanzobjekts der Implementierungsklasse der sqlSession-Schnittstelle Denken Sie daran, die sqlSession-Schnittstelle und die Implementierungsklasse DefaultSqlSession zu erstellen, um die CRUD-Methode von JDBC zu kapseln.
2.2.4. Executor-Schnittstelle und Implementierungsklasse erstellen SimpleExecutor-Implementierungsklasse, erstellen Sie eine Abfragemethode zum Ausführen von JDBC-Code.
Methode: query (Configuration, MappedStatement, Object ... params);
Configuration : Wenn Sie dom4j zum Parsen von sqlMapConfig.xml verwenden, wird der analysierte Inhalt in verschiedenen Formen in das Configuration-Objekt eingekapselt und die Informationen in der Datenbankkonfiguration werden darin gespeichert .
MappedStatement : Wenn Sie dom4j zum Parsen von mapper.xml verwenden, entspricht der Inhalt jedes Tags einem mappedStatement-Objekt, in dem die SQL-Informationen
gespeichert sind. Object ... params : Dies ist der vom Benutzer übergebene Parameter, da nicht sicher ist, wie viele wird getragen. Also Objekt ... Variable Parameter
3.genericTokenParserzheg-Tag-Parser-Klasse
- Diese Klasse kann nur durch parametrisierte Konstruktion erstellt werden
- genericTokenParser ist eine generische Token-Parser-Klasse
- Wenn genericTokenParser # {} Platzhalter analysiert, muss es mit tokenHandler zusammenarbeiten
- Die drei Konstruktionsparameter von genericTokenParser sind Start-Tag, End-Tag und Tag-Prozessor
4. Über sqlessionFactoyBuilder, sqlessionFactoy, sqlession.
- Der beste Bereich von sqlessionFactoyBuilder ist der Methodenbereich, der als lokale Methodenvariable definiert werden kann
- Der beste Bereich von sqlessionFactoy ist der Anwendungsbereich
- Der beste Bereich von sqlession ist der Methodenbereich oder der Anforderungsbereich
5. Informationen zum Rückgabewert resultType und zum Eingabeparameter paramterType
- Der Rückgabewerttyp von resultType lautet: vollständiger Klassenname oder Alias, grundlegende Datentypen sind zulässig, String, int usw.
- Die Datenstruktur von resultType und resultMap ist dieselbe, beide sind Kartenstrukturen
- In mybatis können Sie zusätzlich zur Verwendung der Annotation @param zum Implementieren der Eingabe mehrerer Parameter auch das Map-Objekt zum Implementieren der Übertragung mehrerer Parameter verwenden
6. Schnittstellenentwicklungsspezifikation in mybatis
- Der Namespace in mapper.xml entspricht dem Klassenpfad der Mapper-Schnittstelle
- Der Name der Mapper-Schnittstellenmethode entspricht der ID jeder in mapper.xml definierten Anweisung
- Der Eingabeparametertyp der Mapper-Schnittstellenmethode entspricht dem Parametertyp jedes in mapper.xml definierten SQL
- Der Ausgabeparametertyp der Mapper-Schnittstellenmethode entspricht dem resultType-Typ jeder in mapper.xml definierten SQL
7. Informationen zum Inhalt des mybatis-Quellcodes
- Die beteiligten Entwurfsmuster sind: Agentenmodell, Builder-Modell (Builder / Konstruktor), Factory-Modell, Iterator-Modell
- Die funktionale Architektur kann in drei Schichten unterteilt werden: Schnittstellenschicht, Datenverarbeitungsschicht, Framework-Unterstützungsschicht
- Unterstützt Plug-Ins zum Abfangen von Kernobjekten wie StatementHandler, ParamterHandle und ResultsHandler
- Executor ist der Executor, der für die SQL-Generierung und die Wartung des Abfrage-Cache verantwortlich ist
- statementtHandler kapselt die Operationen der jdbc-Anweisung (die Schnittstelle zum Ausführen von Datenbank-SQL) und ist für die Operation der jdbc-Anweisung verantwortlich
- typeHandler ist für die Zuordnung und Konvertierung zwischen Java-Datentypen und JDBC-Datentypen verantwortlich
- sqlSource ist dafür verantwortlich, SQL-Anweisungen gemäß dem vom Benutzer übergebenen ParameterObject dynamisch zu erstellen und die Informationen in das Objekt boundsql () zu kapseln
8.Mybatis faul laden, was ist das Implementierungsprinzip
Mybatis unterstützt das verzögerte Laden und unterstützt
nur das verzögerte Laden von Zuordnungsobjekten und Sammlungsobjekten. Die
Zuordnung bezieht sich auf Eins-zu-Eins und die Sammlung auf Eins-zu-Viele-Abfragen.
In der Konfigurationsdatei können Sie konfigurieren, ob das verzögerte Laden aktiviert werden soll. LazyLoadingEnabled = true | false.
<settings>
<!-- 打开延迟加载的开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 将积极加载改为消极加载,即延迟加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
Implementierungsprinzip
Verwenden Sie CGLIB, um das Proxy-Objekt des Zielobjekts zu erstellen. Wenn die Zielmethode aufgerufen wird, gibt sie die Interceptor-
Methode ein, und wenn die Daten benötigt werden, ruft sie SQL auf, um die Datenbank abzufragen.
Beispiel: Wenn a.getB (). GetName () aufgerufen wird, stellt die Interceptor-Methode invoke () fest, dass a.getB () ein
Nullwert ist, und sendet die zuvor gespeicherte SQL separat, um das zugehörige B-Objekt abzufragen Rufen Sie dann a.setB (b) auf, sodass das Objekt-b-Attribut von a einen Wert hat, und schließen Sie dann den Aufruf der Methode a.getB (). getName () ab.
9. Die drei Arten von Mybatis Executor, der Unterschied zwischen ihnen
Der Standardwert ist SimplExcutor
SimpleExecutor: Jedes Mal, wenn eine Aktualisierung oder Auswahl ausgeführt wird, wird ein Anweisungsobjekt geöffnet und das Anweisungsobjekt wird unmittelbar nach der Verwendung geschlossen.
ReuseExecutor: Führen Sie die Aktualisierung oder Auswahl aus, verwenden Sie SQL als Schlüssel, um das Anweisungsobjekt zu finden, verwenden Sie es, falls vorhanden, und erstellen Sie es, wenn es nicht vorhanden ist. Nach der Verwendung wird das Anweisungsobjekt nicht geschlossen, sondern in der Map für das platziert nächste Verwendung.
Kurz gesagt, es ist das Statement-Objekt wiederzuverwenden.
BatchExecutor: Update ausführen (keine Auswahl, JDBC-Stapelverarbeitung unterstützt keine Auswahl), alle SQL zum Stapel hinzufügen addBatch (), auf die einheitliche Ausführung von executeBatch () warten, mehrere Anweisungsobjekte zwischenspeichern, jedes Anweisungsobjekt ist Nach addBatch ( ) abgeschlossen, warten Sie nacheinander auf die Stapelverarbeitung von executeBatch ().
Entspricht der JDBC-Stapelverarbeitung.
Handlungsumfang: Diese Eigenschaften von Executor sind streng auf den Umfang des SqlSession-Lebenszyklus beschränkt.
In der Mybatis-Konfigurationsdatei können Sie den Standard-Aktuatortyp ExecutorType angeben oder den Parameter ExecutorType type manuell an die Methode zum Erstellen von SqlSession von DefaultSqlSessionFactory übergeben.
10. Primärer und sekundärer Cache von Mybatis (verteiltes Caching kann nicht implementiert werden, ein Caching-Framework eines Drittanbieters ist erforderlich)
1. Speicherstruktur: Der Cache der ersten Ebene und der Cache der zweiten Ebene werden alle in der HashMap-Struktur zwischengespeichert.
2. Bereich: Der
Cache der ersten Ebene befindet sich auf der SqlSession-Ebene, und der Bereich ist SqlSession. Mybatis aktiviert standardmäßig den Cache der ersten Ebene. Wenn in derselben SqlSession dieselbe SQL abgefragt wird, wird die erste Abfrage aus der Cache Wenn keine Daten vorhanden sind, fragen Sie sie aus der Datenbank ab und zwischenspeichern Sie sie in der HashMap. Die zweite Abfrage wird direkt aus dem Cache abgerufen. Wenn Daten vorhanden sind, werden sie direkt zurückgegeben, ohne die Datenbank zu überprüfen.
Der Cache der zweiten Ebene befindet sich auf der Mapper-Ebene. Mehrere SqlSessions arbeiten mit der SQL-Anweisung desselben Mappers. Mehrere SqlSessions können den Cache der zweiten Ebene gemeinsam nutzen. Der Cache der zweiten Ebene befindet sich über SqlSessions hinweg.
Wenn das SQL unter Mapper zum ersten Mal aufgerufen wird, werden die Informationen abgefragt. Die abgefragten Informationen werden im sekundären Cache-Bereich gespeichert, der dem Mapper entspricht. Beim zweiten Aufruf der Mapper-Zuordnungsdatei unter dem Namespace wird dieselbe SQL aufgerufen wird verwendet, um direkt abzufragen. Rufen Sie das Ergebnis im sekundären Cache ab.
3. Invalidierungsszenario:
Wenn der Cache der ersten Ebene hinzugefügt, gelöscht oder geändert wird, wird der Cache ungültig.
Bei der Verwaltung von Frühjahrscontainern erstellt jede Abfrage eine neue sqlSession, sodass in einer verteilten Umgebung keine Dateninkonsistenz auftritt.
Wenn Sie den Cache der zweiten Ebene verwenden, müssen Sie das Cache-Tag öffnen, das Attribut useCache in der Auswahl auf true setzen und flushCache manuell aktivieren, um den Cache beim Aktualisieren und Löschen zu aktualisieren. Wenn useCache = false gesetzt ist, wird der Cache der zweiten Ebene deaktiviert.
11. Funktionsprinzip des Mybatis-Plug-Ins und Schreiben eines Plug-Ins
Die von MyBatis zugelassenen Abhörmethoden sind folgende:
Ausführender: (Methoden zum Aktualisieren, Abfragen, Festschreiben, Zurücksetzen usw.);
SQL Syntax Builder StatementHandler: ( Methoden zum Vorbereiten, Parametrisieren, Stapeln, Aktualisieren von Abfragen usw.);
Parameterprozessor ParameterHandler : (getParameterObject, setParameters-Methode);
ResultSetHandler: (handleResultSets-, handleOutputParameters- usw. Methoden);
1. Funktionsprinzip:
Mybatis kann Plug-Ins für die vier Schnittstellen Executor, StatementHandler, ParameterHandler und ResultSetHandler schreiben. Mybatis verwendet den dynamischen Proxy von JDK, um Proxy-Objekte für die Schnittstellen zu generieren, die abgefangen werden müssen, und implementiert dann das Abfangen Methode der Schnittstelle, also wenn die Ausführung abgefangen werden muss Wenn die Schnittstellenmethode, wird sie die Abfangmethode eingeben (AOP-Gedanke).
2. So schreiben Sie:
1. Schreiben Sie die Implementierungsklasse der Intercepror-Schnittstelle.
2. Legen Sie die Signatur des Plug-Ins fest und teilen Sie mybatis mit, welche Methode von welchem Objekt abgefangen werden soll.
3. Registrieren Sie das Plug-In schließlich in der globalen Konfigurationsdatei
Beispiel:
package com.njm.plugin;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import java.sql.Connection;
import java.util.Properties;
//插件签名,告诉mybatis当前插件拦截哪个对象的哪个方法
@Intercepts({ //这是个⼤花括号,也就这说这⾥可以定义多个@Signature,对多个地⽅拦截,都⽤这个拦截器
/*
type:表示要拦截的核心(目标)对象,拦截哪个接⼝,StatementHandler是一个sql语句构建器,用来完成sql语句预处理
method:表示要要拦截的方法,prepare是StatementHandler里的sql预编译方法
args:表示要拦截方法的参数,按方法里的参数顺序写,可能方法有重载,所以要通过⽅法名和⼊参来确定唯⼀。
*/
@Signature(type = StatementHandler.class,
method = "prepare",
args = {Connection.class,Integer.class})
})
public class MyPlugin implements Interceptor {
//截方法:只要被拦截的目标对象的目标方法被执行时,每次都会执行intercept方法
@Override
public Object intercept(Invocation invocation) throws Throwable {
/*
* 插件的主要功能:在执行目标方法之前,可以对sql进行修改已完成特定的功能
* 例如增加分页功能,实际就是给sql语句添加limit;还有其他等等操作都可以
* */
System.out.println("对方法进行了增强。。。。。。。");
return invocation.proceed(); //invocation.proceed():原方法执行并返回值
}
//主要为了把当前的拦截器生成代理存到拦截器链中,包装目标对象,为目标对象创建代理对象
@Override
public Object plugin(Object target) {
//target:被拦截的目标对象,this:表示当前自定义的插件实现类,当前拦截器,也就是现在这个类,
//wrap方法利用mybatis封装的方法为目标对象创建代理对象(没有拦截的对象会直接返回,不会创建代理对象)
Object wrap = Plugin.wrap(target, this);
return wrap;
}
//获取配置文件的参数,就是获取插件在配置文件中配置的参数值
//插件初始化的时候调⽤,也只调⽤⼀次,插件配置的属性从这⾥设置进来
@Override
public void setProperties(Properties properties) {
System.out.println("获取到的配置文件的参数是:"+properties);
}
}
Das Plugin ist in der globalen Konfigurationsdatei registriert
<!--配置自定义插件类
interceptor:配置类的路径
property:配置的参数-->
<plugins>
<!--这个是我自定义的插件-->
<plugin interceptor="com.njm.plugin.MyPlugin">
<property name="name" value="tom"/>
</plugin>
<!--这是分页插件,上面的是我自定义的插件-->
<!-- <plugin interceptor="com.github.pagehelper.PageHelper">-->
<!--指定方言-->
<!-- <property name="dialect" value="mysql"/>-->
<!-- </plugin>-->
</plugins>