La première étape. Module un Notes sur le framework personnalisé Mybatis

Répertoire d'articles


Préface

La source de sortie du contenu de l'article: Lagou Education Java High Salary Training Camp. Cours P7
Cet article fait partie des notes après l'école dans le cours d'apprentissage.


adresse du projet

Code projet:
Lien: https://pan.baidu.com/s/1pdtE7NkQb1SHQo9RnfSOTw
Code d'extraction: sc4m

Adresse cloud de code: 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. Problèmes JDBC traditionnels et solutions de framework personnalisées

Questions:
1. La création et la libération fréquentes de connexions à la base de données entraînent un gaspillage des ressources système et affectent ainsi les performances du système.
2. L'instruction sql, le passage de paramètres et le jeu de résultats d'analyse sont tous codés en dur. Les modifications SQL nécessitent de changer le code java, ce qui rend le code difficile à gérer.
Solution:
1. Utilisez le pool de connexions de base de données pour initialiser les ressources de connexion afin de résoudre le problème de la création et de la libération fréquentes de connexions de base de données.
2. Extrayez les instructions sql dans des fichiers de configuration xml, utilisez la réflexion, l'introspection et d'autres technologies sous-jacentes pour mapper automatiquement les entités et les tables en attributs et champs, la réflexion pour définir les paramètres et l'introspection pour renvoyer les résultats Set package.
Modèles de conception impliqués:
modèle de conception de générateur, modèle manuel (fabrique de session), mode proxy (proxy dynamique JDK pour générer des objets proxy pour l'interface Dao)

2. Idées de conception de cadre de couche de persistance personnalisées

2.1. Côté utilisateur (projet): introduire le package jar du framework de couche de persistance personnalisé

  • Fournissez deux parties d'informations de configuration: informations de configuration de base de données, informations de configuration sql (instruction sql, type de paramètre, type de valeur de retour)
  • Utilisez le fichier de configuration pour fournir ces deux parties d'informations de configuration:
    1.sqlMapConfig.xml: stocker les informations de configuration de la base de données, importer mapper.xml.
    2. mapper.xml: stockez les informations de configuration SQL.

2.2. Le framework de couche de persistance personnalisé lui-même (ingénierie): l'essentiel est d'encapsuler JDBC

2.2.1. Lisez le fichier de configuration:

  • Créez une classe pour charger le fichier de configuration dans un flux d'entrée d'octets en fonction du chemin du fichier de configuration et enregistrez-le en mémoire.
    Étapes d'implémentation : création d'une classe Resources, méthode de chargement: InputSteam getResourceAsSteam (String path)
    Les informations de configuration lues sont stockées dans la mémoire sous la forme d'un flux, ce qui n'est pas facile à utiliser. Ici, deux javaBeans (objets conteneurs) sont créés pour une réflexion orientée objet.: Stockez le contenu analysé du fichier de configuration, ce qui est également pratique pour un accès ultérieur.
    Étapes de mise en œuvre : créer deux classes de configuration
    Configuration : classe de configuration principale: stocker le contenu analysé par sqlMapConfig.xml, stocker les informations de base de la base de données, mapper <seul ID, mappeur> ID unique: namespace + "." + Id
    MappedStatement : configuration du mappage class: stocker le contenu analysé par mapper.xml, stocker l'instruction SQL, le type d'instruction, le paramètre d'entrée type java, le paramètre de sortie type java

2.2.2. Analyse du fichier de configuration: j'utilise dom4j ici, mais vous pouvez également utiliser d'autres

Étapes de mise en œuvre:
créez la classe SqlSessionFactoryBuilder, puis créez une méthode: build (InputSteam dans) pour créer la fabrique de session.
Deux choses sont implémentées dans la méthode de construction:
1. Utilisez dom4j pour analyser le fichier de configuration et encapsuler le contenu analysé dans un objet conteneur.
2. Créez un objet SqlSessionFactory (mode usine), produisez un objet de session sqlSession

2.2.3 Créez l'interface SqlSessionFactory et la classe d'implémentation DefaultSqlSessionFactory.

Créez ensuite l'interface SqlSessionFactory et la classe d'implémentation DefaultSqlSessionFactory sur la base du principe d'ouverture et de fermeture. Ecrivez une méthode pour produire sqlSession.
Méthode: openSession () //
Obtient l' objet d'instance de classe d' implémentation de l'interface sqlSession N'oubliez pas de créer l'interface sqlSession et la classe d'implémentation DefaultSqlSession pour encapsuler la méthode CRUD de JDBC.

2.2.4 Créer une interface Executor et une classe d'implémentation Classe d'implémentation SimpleExecutor, créer une méthode de requête pour exécuter le code JDBC.

Méthode: query (Configuration, MappedStatement, Object ... params);
Configuration : Lors de l'utilisation de dom4j pour analyser sqlMapConfig.xml, le contenu analysé sera encapsulé dans l'objet Configuration sous différentes formes, et les informations de la configuration de la base de données sont stockées à l'intérieur .
MappedStatement : Lors de l'utilisation de dom4j pour analyser mapper.xml, le contenu de chaque balise correspond à un objet mappedStatement, qui stocke les informations SQL
Object ... params : Il s'agit du paramètre transmis par l'utilisateur, car il n'est pas sûr de combien sera porté. Donc Objet ... Paramètres variables

3.genericTokenParserzheg classe d'analyseur de balises

  1. Cette classe ne peut être créée que par construction paramétrée
  2. genericTokenParser est une classe d'analyseur de jetons générique
  3. Lorsque genericTokenParser analyse les espaces réservés # {}, il doit coopérer avec tokenHandler
  4. Les trois paramètres de construction de genericTokenParser sont la balise de début, la balise de fin et le processeur de balises

4. À propos de sqlessionFactoyBuilder, sqlessionFactoy, sqlession.

  1. La meilleure portée de sqlessionFactoyBuilder est la portée de la méthode, qui peut être définie comme une variable de méthode locale
  2. La meilleure gamme de sqlessionFactoy est la gamme d'applications
  3. La meilleure portée de sqlession est la portée de la méthode ou la portée de la requête

5. À propos de la valeur de retour resultType et du paramètre d'entrée paramterType

  1. Le type de valeur de retour de resultType est: nom de classe complet ou alias, les types de données de base sont autorisés, String, int, etc.
  2. La structure de données de resultType et resultMap est la même, les deux sont des structures de carte
  3. Dans mybatis, en plus d'utiliser l'annotation @param pour implémenter la saisie de plusieurs paramètres, vous pouvez également utiliser l'objet Map pour implémenter le transfert de plusieurs paramètres

6. Spécification de développement d'interface dans mybatis

  1. L'espace de noms dans mapper.xml est le même que le chemin de classe de l'interface du mappeur
  2. Le nom de la méthode d'interface du mappeur est le même que l'ID de chaque instruction définie dans mapper.xml
  3. Le type de paramètre d'entrée de la méthode d'interface mapper est le même que le type parameterType de chaque SQL défini dans mapper.xml
  4. Le type de paramètre de sortie de la méthode d'interface mapper est le même que le type resultType de chaque sql défini dans mapper.xml

7. À propos du contenu du code source mybatis

  1. Les modèles de conception impliqués sont: modèle d'agent, modèle de constructeur (constructeur / constructeur), modèle d'usine, modèle d'itérateur
  2. L'architecture fonctionnelle peut être divisée en trois couches: couche d'interface, couche de traitement des données, couche de support de structure
  3. Prise en charge des plug-ins pour intercepter les objets principaux tels que statementHandler, paramterHandle et resultsHandler
  4. L'exécuteur est l'exécuteur, responsable de la génération SQL et de la maintenance du cache des requêtes
  5. statementtHandler encapsule les opérations de l'instruction jdbc (l'interface pour exécuter la base de données sql) et est responsable du fonctionnement de l'instruction jdbc
  6. typeHandler est responsable du mappage et de la conversion entre les types de données java et les types de données jdbc
  7. sqlSource est responsable de la production dynamique des instructions SQL en fonction du parameterObject passé par l'utilisateur et de l'encapsulation des informations dans l'objet boundsql ()

8.Mybatis chargement paresseux, quel est son principe de mise en œuvre

Mybatis prend en charge le chargement différé et
ne prend en charge que le chargement différé des objets d'association et des objets de collection; l'
association fait référence à un-à-un et la collection fait référence à une requête un-à-plusieurs.
Dans le fichier de configuration, vous pouvez configurer s'il faut activer le chargement différé lazyLoadingEnabled = true | false.

<settings>
    <!-- 打开延迟加载的开关 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 将积极加载改为消极加载,即延迟加载 -->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

Principe de mise en œuvre
Utilisez CGLIB pour créer l'objet proxy de l'objet cible. Lorsque la méthode cible est appelée, elle entre dans la
méthodeintercepteuret lorsque les données sont nécessaires, elle appelle SQL pour interroger la base de données.
Par exemple: lorsque a.getB (). GetName () est appelé, la méthode de l'intercepteur invoke () trouve que a.getB () est une
valeur nulle, puis elle enverra séparément le sql enregistré à l'avance pour interroger l'objet B associé , et interrogez B. Appelez ensuite a.setB (b) pour que l'attribut objet b de a ait une valeur, puis terminez l'appel de la méthode a.getB (). getName ().

9. Les trois types de Mybatis Executor, la différence entre eux

La valeur par défaut est SimplExcutor
SimpleExecutor: chaque fois qu'une mise à jour ou une sélection est exécutée, un objet Statement est ouvert et l'objet Statement est fermé immédiatement après utilisation.
ReuseExecutor: exécutez la mise à jour ou sélectionnez, utilisez sql comme clé pour trouver l'objet Statement, utilisez-le s'il existe et créez-le s'il n'existe pas. Après utilisation, l'objet Statement n'est pas fermé, mais placé dans la carte pour le utilisation suivante.
En bref, il s'agit de réutiliser l'objet Statement.
BatchExecutor: exécutez la mise à jour (pas de sélection, le traitement par lots JDBC ne prend pas en charge la sélection), ajoutez tout SQL au lot addBatch (), attendez l'exécution unifiée de executeBatch (), il met en cache plusieurs objets Statement, chaque objet Statement est After addBatch ( ) se termine, attendez le traitement par lots de executeBatch () un par un.
Identique au traitement par lots JDBC.

Champ d'action: Ces caractéristiques d'Executor sont strictement limitées à la portée du cycle de vie de SqlSession.

Dans le fichier de configuration Mybatis, vous pouvez spécifier le type d'actionneur ExecutorType par défaut, ou vous pouvez passer manuellement le paramètre de type ExecutorType à la méthode de création de SqlSession de DefaultSqlSessionFactory.

10. Les caches principaux et secondaires de Mybatis (la mise en cache distribuée ne peut pas être mise en œuvre, un cadre de mise en cache tiers est requis)

1. Structure de stockage: le cache de premier niveau et le cache de second niveau sont tous mis en cache dans la structure HashMap.
2. Portée: Le
cache de premier niveau est au niveau SqlSession et la portée est SqlSession. Mybatis active le cache de premier niveau par défaut. Dans la même SqlSession, lorsque le même Sql est interrogé, la première requête sera prise à partir du cache S'il n'y a pas de données, interrogez-les à partir de la base de données et mettez-les en cache dans le HashMap. La deuxième requête est directement extraite du cache, et s'il y a des données, elle est renvoyée directement sans vérifier la base de données.

Le cache de second niveau se trouve au niveau du mappeur. Plusieurs SqlSessions fonctionnent sur l'instruction SQL du même mappeur. Plusieurs SqlSessions peuvent partager le cache de second niveau. Le cache de second niveau se trouve dans les SqlSessions.
Lorsque le sql sous mapper est appelé pour la première fois, les informations sont interrogées. Les informations interrogées seront stockées dans la zone de cache secondaire correspondant au mappeur. La deuxième fois que le fichier de mappage du mappeur sous l'espace de noms est appelé, le même SQL est utilisé pour interroger directement. Récupérer le résultat dans le cache secondaire.

3. Scénario d'invalidation:
lorsque le cache de premier niveau est ajouté, supprimé ou modifié, le cache sera invalidé.
Dans la gestion des conteneurs Spring, chaque requête crée une nouvelle sqlSession, il n'y aura donc aucune incohérence de données dans un environnement distribué.

Lorsque vous utilisez le cache de deuxième niveau, vous devez ouvrir la balise de cache, ajouter l'attribut useCache à true lors de la sélection et activer manuellement flushCache pour actualiser le cache lors de la mise à jour et de la suppression. Si useCache = false est défini, le cache de deuxième niveau est désactivé.

11. Principe de fonctionnement du plug-in Mybatis et comment écrire un plug-in

Les méthodes d'interception autorisées par MyBatis sont les suivantes:
Executor: ( méthodes de mise à jour, requête, validation, restauration, etc.);
Générateur de syntaxe SQL StatementHandler: ( méthodes de préparation, paramétrage, batch, requête de mises à jour, etc.);
Processeur de paramètres ParameterHandler : (getParameterObject, méthode setParameters);
ResultSetHandler: (méthodes handleResultSets, handleOutputParameters, etc.);

1. Principe de fonctionnement:
Mybatis peut écrire des plug-ins pour les quatre interfaces d'Executor, StatementHandler, ParameterHandler et ResultSetHandler. Mybatis utilise le proxy dynamique de JDK pour générer des objets proxy pour les interfaces qui doivent être interceptées, puis implémente l'interception. méthode de l'interface, donc lorsque l'exécution doit être interceptée Lorsque la méthode d'interface, il entrera dans la méthode d'interception (AOP pensé).
2. Comment écrire:
1. Ecrivez la classe d'implémentation de l'interface Intercepror
2. Définissez la signature du plug-in, indiquez à mybatis quelle méthode de quel objet intercepter
3. Enfin, enregistrez le plug-in dans le fichier de configuration globale

Exemple:

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);
    }
}

Le plugin est enregistré dans le fichier de configuration globale

 <!--配置自定义插件类
        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>

Je suppose que tu aimes

Origine blog.csdn.net/weixin_39417423/article/details/108332236
conseillé
Classement