美文网首页
Java进阶-MyBatis

Java进阶-MyBatis

作者: GIT提交不上 | 来源:发表于2022-05-16 21:36 被阅读0次

    一、参考资料

    MyBatis官网
    玩转 MyBatis:深度解析与定制
    Mybatis介绍
    为什么建议框架源码学习从Mybatis开始

    二、整体结构

    image.png

    三、配置文件

    https://mybatis.org/mybatis-3/zh/configuration.html#settings

    3.1 配置文件加载

    InputStream xml = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(xml);
    
    • 通过ClassLoader获取到全局配置文件的二进制流
    • XMLConfigBuilder构建SqlSessionFactory
    MyBatis配置文件加载.png

    3.2 Mapper.xml的解析

    XMLConfigBuilder#parseConfiguration
    mapperElement(root.evalNode("mappers"));
    
    Mapper.xml解析.png

    四、缓存

      一级缓存基于SqlSession,可以直接创建SqlSessionFactory,并从中开启一个新的SqlSession,默认情况下它会自动开启事务。

      一级缓存失效的情景:

    • 跨SqlSession的一级缓存不共享
    • 两次相同的查询间有DML操作
    • 手动清空了一级缓存

      SpringFramework/SpringBoot整合MyBatis后,Service方法中没有开启事务时,每次调用Mapper查询数据时,底层都会创建一个全新的SqlSession去查数据库。

    BaseExecutor#query
    protected PerpetualCache localCache;
    
    • SqlSession关闭时,一级缓存的数据进入二级缓存
    • 二级缓存中有数据时,直接取出,不会预先开启Connection
    • 二级缓存基于nameSpace级别
    CachingExecutor#query
    
    private final TransactionalCacheManager tcm = new TransactionalCacheManager();
    
    public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, 
                             ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        Cache cache = ms.getCache();
        if (cache != null) {
            flushCacheIfRequired(ms);
            if (ms.isUseCache() && resultHandler == null) {
                ensureNoOutParams(ms, boundSql);
                List<E> list = (List<E>) tcm.getObject(cache, key);
                if (list == null) {
                    list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
                    tcm.putObject(cache, key, list); // issue #578 and #116
                }
                return list;
            }
        }
        return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    }
    

       TransactionalCacheManager:二级缓存应该是基于事务提交的,只有事务提交后,数据库的数据确定没有问题,这个时候SqlSession中的一级缓存数据也是准确的,这样才能把一级缓存的数据写入到二级缓存中。

       二级缓存在写入时已经执行了一次基于jdk的序列化动作,每次从二级缓存取数据时,会再执行一次反序列化,将字节数组转为缓存数据对象。

    五、日志

      Logger增强类-动态代理。

    • PreparedStatementLogger
    • ConnectionLogger
    • ResultSetLogger

    六、Spring整合MyBatis

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- MyBatis全局配置文件 -->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="typeAliasesPackage" value="com.linkedbear.mybatis.entity"/>
    </bean>
    

      SqlSessionFactoryBean:只负责mapper.xml的处理。

    public class SqlSessionFactoryBean
           implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
    
       // ......
    
       private Resource configLocation;
    
       private Configuration configuration;
    
    • 几乎可以代替MyBatis全局配置文件
    • 可以传入全局配置文件,供MyBatis解析和处理
    • 代替MyBatis处理数据源和事务工厂
    • 只处理和解析mapper.xml

      MapperScannerConfigurer:扫描Mapper接口。

    public class MapperScannerConfigurer
            implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
    
        private SqlSessionFactory sqlSessionFactory;
    
        private SqlSessionTemplate sqlSessionTemplate;
    
        private String sqlSessionFactoryBeanName;
    
        private String sqlSessionTemplateBeanName;
    

      ClassPathMapperScanner,它会执行包扫描的动作,并且将扫描到的Mapper接口都收集起来,构造成MapperFactoryBeanMapper,注入到SqlSessionFactory和SqlSessionTemplate。

    七、生命周期

      整体结构:

    image.png

      Executor类结构:

    image.png
    • CRUD操作
    • 事务控制和获取
    • 二级缓存的控制
    • 延迟加载

      selectList的整体调用时序图:

    image.png
    • SqlSource中传入参数,返回BoundSql的过程,会将动态SQL解析转化为可以执行的带占位符的SQL语句
    image.png

    相关文章

      网友评论

          本文标题:Java进阶-MyBatis

          本文链接:https://www.haomeiwen.com/subject/ukrkurtx.html