首页 > 编程语言 >MyBatis 源码系列:MyBatis 体系结构、六大解析器

MyBatis 源码系列:MyBatis 体系结构、六大解析器

时间:2024-01-28 18:13:44浏览次数:30  
标签:解析器 boolean public apache protected MyBatis import 源码

体系结构

MyBatis是一个持久层框架,其体系结构分为三层:基础支持层、核心处理层和接口层。

基础支持层包括数据源模块、事务管理模块、缓存模块、Binding模块、反射模块、类型转换模块、日志模块、资源加载模块和解析器模块。这些模块为MyBatis提供了基础功能,为核心处理层提供了良好的支撑。

核心处理层包括配置解析、参数映射、SQL解析、SQL执行、结果集映射和插件。这些组件共同完成了MyBatis的核心处理逻辑,包括将SQL语句与输入参数进行映射,解析SQL语句,执行SQL语句,并将结果映射回Java对象等。

接口层是MyBatis与上层应用交互的桥梁,包括SqlSession接口。SqlSession是MyBatis中最重要的接口之一,它定义了MyBatis保留给应用的API,用于执行各种数据库操作,如查询、插入、更新和删除等。

在MyBatis的体系结构中,还有一个重要的组成部分是全局配置文件。全局配置文件包含了MyBatis的运行环境等信息,通过解析全局配置文件,MyBatis可以完成基本配置的初始化,并根据配置信息实例化相应的组件。

总的来说,MyBatis的体系结构是一个层次分明、模块化的结构,各层之间相互依赖、协同工作,共同完成了MyBatis的核心功能和操作数据库的逻辑。通过这种结构,MyBatis能够有效地封装底层的JDBC操作,让用户专注于SQL语句的编写和数据库操作,提高了开发效率和代码的可维护性。

image

六大解析器

MyBatis的六大解析器Builder分别是:

  1. XMLConfigBuilder:用于构建 MyBatis 的配置信息,包括数据源、事务管理器等信息。
  2. XMLMapperBuilder:用于构建 Mapper 的 XML 配置文件。该 Builder 读取 Mapper 的 XML 文件,将其解析为 SqlSessionFactory 的一个实例,以便在后续的操作中使用。
  3. MapperBuilderAssistant:用于协助构建 Mapper 的 XML 配置文件。该 Builder 提供了一系列方法,用于简化 Mapper XML 文件的构建过程。
  4. XMLStatementBuilder:用于构建 SQL 语句的 Builder。该 Builder 负责解析 SQL 语句,并将其转换为 MyBatis 可以执行的内部表示形式。
  5. XMLScriptBuilder:用于构建 XML 脚本的 Builder。该 Builder 提供了一些方法,用于构建执行 DDL(数据定义语言)操作的 XML 脚本,例如创建表、视图等。
  6. SqlSourceBuilder:用于构建 SQL 语句的源代码。该 Builder 读取 MyBatis 的映射文件中的 <sql> 标签,将其解析为 SqlSource 对象,以便在执行 SQL 语句时使用。

image

注意:最终解析的都会存入 Configuration 对象中

package org.apache.ibatis.session;

/**
 * @author Clinton Begin
 */
public class Configuration {

  protected Environment environment;

  protected boolean safeRowBoundsEnabled;
  protected boolean safeResultHandlerEnabled = true;
  protected boolean mapUnderscoreToCamelCase;
  protected boolean aggressiveLazyLoading;
  protected boolean multipleResultSetsEnabled = true;
  protected boolean useGeneratedKeys;
  protected boolean useColumnLabel = true;
  protected boolean cacheEnabled = true;
  protected boolean callSettersOnNulls;
  protected boolean useActualParamName = true;
  protected boolean returnInstanceForEmptyRow;
  protected boolean shrinkWhitespacesInSql;
  protected boolean nullableOnForEach;
  protected boolean argNameBasedConstructorAutoMapping;

  ...
}

image

全部代码

SQL 脚本

create database test;
create table test.user
(
    id          int auto_increment
        primary key,
    user_name   varchar(50) not null,
    create_time datetime    not null
);

mybaits-cofig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="db.properties"></properties>
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <plugins>
        <plugin interceptor="com.mcode.plugin.ExamplePlugin" ></plugin>
    </plugins>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <!--//  mybatis内置了JNDI、POOLED、UNPOOLED三种类型的数据源,其中POOLED对应的实现为org.apache.ibatis.datasource.pooled.PooledDataSource,它是mybatis自带实现的一个同步、线程安全的数据库连接池 一般在生产中,我们会使用c3p0或者druid连接池-->
            <dataSource type="POOLED">
            <property name="driver" value="${mysql.driverClass}"/>
            <property name="url" value="${mysql.jdbcUrl}"/>
            <property name="username" value="${mysql.user}"/>
            <property name="password" value="${mysql.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!--1.必须保证接口名(例如IUserDao)和xml名(IUserDao.xml)相同,还必须在同一个包中-->
        <package name="com.mcode.mapper"/>

        <!--2.不用保证同接口同包同名
         <mapper resource="com/mybatis/mappers/EmployeeMapper.xml"/>

        3.保证接口名(例如IUserDao)和xml名(IUserDao.xml)相同,还必须在同一个包中
        <mapper class="com.mybatis.dao.EmployeeMapper"/>

        4.不推荐:引用网路路径或者磁盘路径下的sql映射文件 file:///var/mappers/AuthorMapper.xml
         <mapper url="file:E:/Study/myeclipse/_03_Test/src/cn/sdut/pojo/PersonMapper.xml"/>-->
    </mappers>
</configuration>

db.properties

mysql.driverClass=com.mysql.cj.jdbc.Driver
mysql.jdbcUrl=jdbc:mysql://127.0.0.1/test?characterEncoding=utf8
mysql.user= root
mysql.password= 123456

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.mcode.mapper.UserMapper">
    <cache ></cache>
    <!-- Mybatis 是如何将 sql 执行结果封装为目标对象并返回的?都有哪些映射形式?-->
    <resultMap id="result" type="com.mcode.entity.User">
        <id column="id" jdbcType="INTEGER" property="id"/>
        <result column="user_name" jdbcType="VARCHAR" property="userName"/>
        <result column="create_time" jdbcType="DATE" property="createTime"/>
        <!--<collection property="" select=""-->

    </resultMap>
    <!--namespace根据自己需要创建的的mapper的路径和名称填写-->
    <select id="selectById" resultMap="result">
        select * from user
        <where>
            <if test="id > 0">
                and id = #{id}
            </if>
        </where>
    </select>
</mapper>

User.java

package com.mcode.entity;

import java.time.LocalDateTime;

/**
 * ClassName: User
 * Package: com.mcode.entity
 * Description:
 *
 * @Author: robin
 * @Version: v1.0
 */
public class User {
    private int id;
    private String userName;

    private LocalDateTime createTime;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public LocalDateTime getCreateTime() {
        return createTime;
    }

    public void setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
    }
}

UserMapper.java

package com.mcode.entity;

import java.time.LocalDateTime;

/**
 * ClassName: User
 * Package: com.mcode.entity
 * Description:
 *
 * @Author: robin
 * @Version: v1.0
 */
public class User {
    private int id;
    private String userName;

    private LocalDateTime createTime;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public LocalDateTime getCreateTime() {
        return createTime;
    }

    public void setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
    }
}

ExamplePlugin.java

package com.mcode.plugin;

/**
 * ClassName: ExamplePlugin
 * Package: com.mcode.plugin
 * Description:
 *
 * @Author: robin
 * @Version: v1.0
 */

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;


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

    //  分页   读写分离    Select  增删改

    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("代理");
        Object[] args = invocation.getArgs();
        MappedStatement ms= (MappedStatement) args[0];
        // 执行下一个拦截器、直到尽头
        return invocation.proceed();
    }

}

App.java

package com.mcode;

import com.mcode.entity.User;
import com.mcode.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.Reader;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
        String resource = "mybatis-config.xml";
        Reader reader;
        try {
            //将XML配置文件构建为Configuration配置类
            reader = Resources.getResourceAsReader(resource);
            // 通过加载配置文件流构建一个SqlSessionFactory  DefaultSqlSessionFactory
            SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);
            // 数据源 执行器  DefaultSqlSession
            SqlSession session = sqlMapper.openSession();
            sqlMapper.getConfiguration();
            try {
                UserMapper mapper = session.getMapper(UserMapper.class);
                System.out.println(mapper.getClass());
                User user = mapper.selectById(1);
                System.out.println(user.getUserName());
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                session.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

标签:解析器,boolean,public,apache,protected,MyBatis,import,源码
From: https://www.cnblogs.com/vic-tory/p/17993094

相关文章

  • 通达信 深海预警指标公式源码副图
    80,COLOR888888,; QW1:=(HIGH+LOW+CLOSE*2)/4; QW3:=EMA(QW1,10); QW4:=STD(QW1,10); QW5:=(QW1-QW3)*100/QW4; QW6:=EMA(QW5,5); RK7:=EMA(QW6,10);涨:EMA(QW6,10)+100/2-5,LINETHICK1,COLORYELLOW;跌:=EMA(涨,4),LINETHICK1,COLORFFFF34,;多线:IF(CROSS(涨,跌)A......
  • 通达信启动买入主图指标公式源码
    A:EMA(C,21)COLORBLUE,LINETHICK3; B:=A<ref(a,1); IF(B-1,A,DRAWNULL)COLORRED,LINETHICK3; AA:=EMA(C,3)>EMA(C,21); BB:=EMA(C,3)<EMA(C,21); CC:=EMA(C,3)>EMA(C,8); CC1:=EMA(C,3)<EMA(C,8); DD:=CLOSE<open;STICKLINE(AA,H,L,0,0),C......
  • 通达信【寻妖记】幅图选股公式 大概率捉妖 简洁浓缩 分析股票的强度指标 源码文件分享
    通达信【寻妖记】幅图选股公式简洁浓缩分析股票的强度指标源码文件分享原公式完全加密,时间限时,股海网解密源码文件分享,已经解除时间限制,可以永久使用,并新增选股公式一个本指标叠加了资金流动、筹码流动、股票情绪三个元素,是一个综合性的评价指标,可用于选股、操盘。这个指标......
  • 通达信启动与洗盘指标公式源码
    volUME:VOL,VOLstICK;主力启动线:ma(VOLUME,5),COLORRED,LINETHICK1;主力洗盘线:MA(VOLUME,35),COLORYELLOW,LINETHICK1;资金异动线:MA(VOLUME,135),COLORWHITE,LINETHICK1;出击:STICKLINE(crOSS(主力启动线,资金异动线)OR((主力洗盘线>资金异动线)ANDCROSS(主力启动线,......
  • 通达信抓大牛主图指标公式源码主图
    M3:ma(CLOSE,3);M13:MA(CLOSE,13);M34:MA(CLOSE,34),COLORRED,LINETHICK2;X:=BArslAst(REF(crOSS(C,MA(C,120)),1))ANDCROSS(MA(C,20),MA(C,120));IF(M34<ref(m34,1),m34,drawnull),colorgreen,linethick2;STICKLINE(M3>=M13ANDM34>=REF(M34,1),H,L,0.1,0......
  • 通达信赤霞捉妖指标公式源码副图
    {日周月趋势}月DIF:=(Ema(CLOSE,12*4*4)-EMA(CLOSE,26*4*4));月DEA:=EMA(月DIF,9*4*4);月macd:=2*(月DIF-月DEA);周DIF:=(EMA(CLOSE,12*4)-EMA(CLOSE,26*4));周DEA:=EMA(周DIF,9*4),COLORWHITE,DOTLINE;周MacD:=2*(周DIF-周DEA);日DIF:=(EMA(CLOSE,12)-EMA(CLOSE,26));日D......
  • 通达信超级生命线指标公式源码副图
    LASBAR:=BARstATUS==2;volX:=IF(LASBAR,DYNAINFO(17)*DYNAINFO(38),0),LINETHICK0;STICKLINE(LASBAR,0,VOLX,7.5,1)COLORYELLOW;VOLUME:VOL,VOLSTICK;BLZ:=VOL>REF(V,1)*1.9;BLZ1:=VOL<REF(LLV(VOL,13),1);BLZ2:=VOL<REF(LLV(VOL,55),1);HJZ:=(3*C+H+L+O)/6......
  • 通达信卧龙根副图指标公式源码副图
    跟庄看盘:DRAWNULL,COLOR0088FF;DT:=L=DTPRICE(REF(C,1),0.1);ZT:=C=ZTPRICE(REF(C,1),0.1);连阴:=COUNT((C<REF(C,1)ORL<REF(L,1)),10)>=5;间谍柱:=REF(连阴,1)ANDDT;卧底:=BArslAst(间谍柱);卧龙根:卧底<20ANDcrOSS(C,REF((C+O)/2,卧底));洗龙根:EXIST(卧龙根,1......
  • 通达信卧龙根主图指标公式源码
    跟庄看盘:DRAWNULL,COLOR0088FF;DRAWKLINE(H,O,L,C);ma5:MA(C,5);昨半:REF((C+O)/2,1),COLORYELLOW,NODRAW;半分:(C+O)/2,NODRAW,COLORWHITE;TM:=1200823;涨停:IF(DATE<tm,ztprice(ref(c,1),if(codelike('688'),0.2,if(nameinclude('s'),0.05,0.1))),ztpri......
  • 通达信分时T+0指标公式源码主图
    ma30:=EMA(CLOSE,30);强弱:EMA(CLOSE,900);stICKLINE((MA30>强弱),MA30,强弱,1,0),COLOR0000FF;STICKLINE((MA30<强弱),MA30,强弱,1,0),COLOR00FF00;H1:=MAX(DYNAINFO(3),DYNAINFO(5));L1:=MIN(DYNAINFO(3),DYNAINFO(6));P1:=H1-L1;阻力:L1+P1*7/8,COLOR00DD00;支撑:L1+P1......