加载中...

MyBatis的大体印象

MyBatis笔记

使用样例

// 只使用MyBatis
public static void main(String[] args) throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        try (
            SqlSession sqlSession = sqlSessionFactory.openSession()
        ) {
            AppUserMapper userMapper = sqlSession.getMapper(AppUserMapper.class);
            String name = userMapper.getName(7);
            // 使用user对象
            System.out.println(name);
        }
    }
@Mapper
public interface AppUserMapper{

    String getName(Integer id);

}
<?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="org.apache.test.mapper.AppUserMapper">

    <select id="getName">
        select name
        from ap_user
        where id = #{id}
    </select>
</mapper>

启动流程

  1. 创建SqlSessionFactory

    • 在创建SqlSessionFactory的过程中,会初始化XMLConfigBuilder (随便会初始化Configuration)该对象会解析mybatis-config.xml 文件,并解析文件中的标签,保存标签中的属性,或创建标签对应的对象,所有的属性和对象均会被保存在Configuration

    • private void parseConfiguration(XNode root) {
              try {
                  // 处理<properties>标签,定义KV信息供MyBatis使用
                  propertiesElement(root.evalNode("properties"));
                  // 处理<settings>标签,MyBatis全局性的配置
                  Properties settings = settingsAsProperties(root.evalNode("settings"));
                  loadCustomVfs(settings);
                  // 处理Log
                  loadCustomLogImpl(settings);
                  // 处理<typeAliases>标签
                  typeAliasesElement(root.evalNode("typeAliases"));
                  // 处理<plugins>标签
                  pluginElement(root.evalNode("plugins"));
                  // 处理<objectFactory>标签
                  objectFactoryElement(root.evalNode("objectFactory"));
                  // 处理<objectWrapperFactory>标签
       objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
                  // 处理<reflectorFactory>标签
                reflectorFactoryElement(root.evalNode("reflectorFactory"));
                  // 处理settings的相关标签
                  settingsElement(settings);
                  // 处理<environments>标签
                  environmentsElement(root.evalNode("environments"));
                  // 处理<databaseIdProvider>标签
            databaseIdProviderElement(root.evalNode("databaseIdProvider"));
                  // 处理<typeHandlers>标签
                  typeHandlerElement(root.evalNode("typeHandlers"));
                  // 处理<mappers>标签
                  mapperElement(root.evalNode("mappers"));
              } catch (Exception e) {
                  throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
              }
          }
      
    • 在解析的过程中,会创建的对象包括:

      1. TypeAliasRegistry;别名注册器,保存别名与类之间的关系。
      2. InterceptorChain:插件链,保存所有的插件,组成链条。
      3. ObjectFactory:用于创建对象。
      4. ObjectWrapperFactory:创建 ObjectWrapper ,用于简化对对象属性的访问。
      5. ReflectorFactory:获取Reflector(类信息的包装)。
      6. TransactionFactory:事务工厂
      7. DataSourceFactory:数据源工厂->有池化和无池化两种连接池。
      8. databaseIdProvider:确定当前数据库的类型(例如 MySQL、Oracle 或 PostgreSQL)。
      9. TypeHandlerRegistry:类型转换注册器,java类型与数据库类型间的转换。
      10. MapperRegistry:Mapper接口与它的创建工厂。实现mapper接口与Mapper.xml文件

使用流程

SqlSession sqlSession = sqlSessionFactory.openSession()

  1. 创建Executor对象,执行SQL语句的对象。

    • BatchExecutor:批量操作
    • ReuseExecutor:可重用,相同SQL只会进行一次预处理
    • SimpleExecutor:每次都会进行预编译

    注意:如果开启二级缓存,则会在创建的Executor对象上在包一层,创建CachingExecutor

  2. 在Executor的基础上创建DefaultSqlSession对象

    1. 包括select,update,delete,insert,commit,rollback等方法。

执行流程

AppUserMapper userMapper = sqlSession.getMapper(AppUserMapper.class)

  1. 通过DefaultSqlSession对象的getMapper方法,拿到AppUserMapper 接口的代理对象。
    • 最终来到MapperRegistry的getMapper方法,拿到MapperProxyFactory对象,通过该对象的newInstance()方法,最后调用jdk的动态代理创建对象。
    • newInstance()方法中,会创建MapperProxy对象,该对象是动态代理的真正对象。保存了接口的相关信息,如:代理的接口,接口的方法和Invoker(反射),sqlSession等;

方法执行过程

String name = userMapper.getName(7);

sql执行前

  1. 会进入到代理对象MapperProxyinvoke()方法中。在方法中,会根据传入的Method,获取该Method的MapperMethodInvoker,(缓存中有,直接获取,没有就创建,并保存在缓存中)。

    • DefaultMethodInvoker:借助MethodHandle执行方法,有JVM提供支持,性能更高。
    • PlainMethodInvoker:依赖MapperMethod执行方法。

    MapperMethod介绍:

    1. 保存了sql语句相关信息,如具体sql语句,语句的类型等。
    2. 保存了接口方法的相关信息,如方法的返回值类型。
  2. 大部分情况会调用MapperMethodexecute()方法。

  3. 通过SqlSession相关的select,update,delete,insert等方法,底层是Executor的相关方法。

  4. 创建StatementHandler,并为Sql语句设置参数。最后调用jdbc的Statement执行语句。

sql执行后

  1. insert,delete,update会返回一个数字,直接通过typeHandler转换即可。
  2. select:通过Executor的query方法,执行sql查询,处理各种复杂情况,如嵌套查询,多结果集查询,一二级缓存,延迟加载等。查询逻辑有缓存中查数据库查
  3. 还是通过jdbc的Statement执行语句。结果在Statement对象中。
  4. 调用resultSetHandler对结果进行处理,包括创建结果集,处理嵌套,类型转换等。

MyBatis与Spring整合。

  1. 由自己提供SqlSessionFactoryBean,和SqlSessionFactory差不多。
  2. 当有了SqlSessionFactory,就可以获得SqlSession,有了SqlSession就可以通过getMapper获得接口的代理类,这样我们的接口就交给Spring管理了。

MyBatis与SpringBoot整合。

由于SqlSessionFactoryBean已经通过自动装配创建好了。

所有在使用时就只需要写Mapper.xml文件和具体接口。

posted @ 2024-07-14 11:17  strind  阅读(43)  评论(0)    收藏  举报