简略分析Mybatis 源码

Mybatis简略工作原理。本文建立在Spring+SpringMVC+Mybatis整合的项目之上。

我将其工作原理分为六个部分:

  1. 读取核心配置文件mybatis-config.xml并返回InputStream流对象。
  2. 根据InputStream流对象解析出Configuration对象,然后创建SqlSessionFactory工厂对象。
  3. 根据一系列属性从SqlSessionFactory工厂中创建SqlSession。
  4. 从SqlSession中调用Executor执行数据库操作&&通过解析生成具体SQL指令。
  5. 通过TypeHandler(数据库与java类型转换)对执行结果进行二次封装。
  6. 提交与事务处理。

具体结合代码看:

/**
 1. 人实体
 */
public class People {

    private String name;// 姓名

    private String sex;// 性别

    private int phone;// 手机号

        getter and setter ...
}

1. 读取核心配置文件

1.1配置文件mybatis-config.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>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://xxx.xxx:3306/ssm" />
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
        <mappers>
        <mapper resource="PeopleMapper.xml"/>
    </mappers>
</configuration>

当然,还有很多可以在XML 文件中进行配置,上面的示例指出的则是最关键的部分。要注意 XML 头部的声明,用来验证 XML 文档正确性。environment 元素体中包含了事务管理和连接池的配置。mappers 元素则是包含一组 mapper 映射器(这些 mapper 的 XML 文件包含了 SQL 代码和映射定义信息)。

1.2 PeopleMapper.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="Book">
    <!-- 目的:为dao接口方法提供sql语句配置 -->
    <insert id="insert" >
        insert into user (name,phone,sex) values (#{name},#{number},#{sex})
    </insert>
</mapper>

就是一个普通的mapper.xml文件。

1.3 Main方法
从 XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件进行配置。但是也可以使用任意的输入流(InputStream)实例,包括字符串形式的文件路径或者 file:// 的 URL 形式的文件路径来配置。MyBatis 包含一个名叫 Resources 的工具类,它包含一些实用方法,可使从 classpath 或其他位置加载资源文件更加容易。
public class Main {
    public static void main(String[] args) throws IOException {
        // 创建一个book对象
        Book book = new Book();
        book.setBookId(1006);
        book.setName("Easy Coding");
        book.setNumber(110);
        // 加载配置文件 并构建SqlSessionFactory对象
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        // 从SqlSessionFactory对象中获取 SqlSession对象
        SqlSession sqlSession = factory.openSession();
        // 执行操作
        sqlSession.insert("insert", book);
        // 提交操作
        sqlSession.commit();
        // 关闭SqlSession
        sqlSession.close();
    }
}

这个代码是根据Mybatis官方提供的一个不使用 XML 构建 SqlSessionFactory的一个Demo改编的。

注意:是官方给的一个不使用 XML 构建 SqlSessionFactory的例子,那么我们就从这个例子中查找入口来分析。

2. 根据配置文件生成SqlSessionFactory工厂对象

2.1 Resources.getResourceAsStream(resource);源码分析
```Resources```是mybatis提供的一个加载资源文件的工具类。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190320214600530.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDczOTM0OQ==,size_16,color_FFFFFF,t_70)

我们只看getResourceAsStream方法:

public static InputStream getResourceAsStream(String resource) throws IOException {
    return getResourceAsStream((ClassLoader)null, resource);
}

getResourceAsStream调用下面的方法:

public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {
    InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
    if (in == null) {
        throw new IOException("Could not find resource " + resource);
    } else {
        return in;
    }
}

获取到自身的ClassLoader对象,然后交给ClassLoader(lang包下的)来加载:

InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
    ClassLoader[] arr$ = classLoader;
    int len$ = classLoader.length;

    for(int i$ = 0; i$ < len$; ++i$) {
        ClassLoader cl = arr$[i$];
        if (null != cl) {
            InputStream returnValue = cl.getResourceAsStream(resource);
            if (null == returnValue) {
                returnValue = cl.getResourceAsStream("/" + resource);
            }

            if (null != returnValue) {
                return returnValue;
            }
        }
    }

值的注意的是,它返回了一个InputStream对象。

发布了12 篇原创文章 · 获赞 8 · 访问量 3834

猜你喜欢

转载自blog.csdn.net/weixin_44739349/article/details/88701172