【MyBatis】mybatis执行流程与缓存机制分析

原创 2016年08月29日 11:23:42

1. 编程式使用mybatis


首先,我们直观地看一下怎样编程式(非配置式)使用mybatis作为ORM框架实现数据库的基本操作。

    private static void testId() throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = factory.openSession();

        // 获取代理 -> MapperProxy
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);

        Student student = new Student();
        student.setStudentName("AutoIncrementId");
        student.setStudentNumber("2014216003");
        // sqlSession.insert("insertEntry", student);
        studentDao.insertEntry(student);
        System.out.println(student.getId());// 3

        // commit & close
        sqlSession.commit();
        sqlSession.close();
    }

可以清晰地看到一共分为三个步骤:第一步,使用mybatis配置文件创建SqlSessionFactory,并打开一个sqlSession;第二步,获取代理MapperProxy类;第三步,执行数据库基本操作。

2. 第一步,获取sqlSession



图片来源:深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇)

3. 第二步,获取代理MapperProxy


3.0 
sqlSession.getMapper(StudentDao.class);
3.1  DefaultSqlSession
	public <T> T getMapper(Class<T> type)
		configuration.<T>getMapper(type, this);
3.2 Configuration
	public <T> T getMapper(Class<T> type, SqlSession sqlSession)
		mapperRegistry.getMapper(type, sqlSession);
3.3 MapperRegistry
	public <T> T getMapper(Class<T> type, SqlSession sqlSession)
		mapperProxyFactory.newInstance(sqlSession);
3.4 MapperProxyFactory
	public T newInstance(SqlSession sqlSession)
		(T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
3.5 Proxy
	public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)


图片来源:深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇)

4. 第三步,执行数据库操作


4.1 MapperProxy
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
		mapperMethod.execute(sqlSession, args);
4.2 MapperMethod
	public Object execute(SqlSession sqlSession, Object[] args)
		sqlSession.insert(command.getName(), param)
4.3 DefaultSqlSession
	public int insert(String statement, Object parameter)
		update(statement, parameter);
public intupdate(String statement, Object parameter)
executor.update(ms, wrapCollection(parameter));
4.4 CachingExcutor
public intupdate(MappedStatement ms, Object parameterObject)throwsSQLException
delegate.update(ms, parameterObject);
4.5 BaseExcutor
public intupdate(MappedStatement ms, Object parameter)throwsSQLException
doUpdate(ms, parameter);
4.6 SimpleExcutor
public intdoUpdate(MappedStatement ms, Object parameter)
handler.update(stmt);
4.7 PreparedStatementHandler
  public int update(Statement statement) throws SQLException {
    PreparedStatement ps = (PreparedStatement) statement;
    ps.execute();
    int rows = ps.getUpdateCount();
    Object parameterObject = boundSql.getParameterObject();
    KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
    keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
    return rows;
  }




图片来源:深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇)

5. MyBatis缓存机制分析


    private static void testCache() throws IOException {
        InputStream is = Resources.getResourceAsStream("mybatis-config2.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = factory.openSession();

        long id = 1L;
        Student student = new Student();
        student.setStudentName("Ethan");
        student.setStudentNumber("2014216001");
        sqlSession.insert("insertEntry", student);
        System.out.println(student.getId());// null

        // query from db
        // 加入一级缓存和二级transactional缓存,由于sqlsession未commit,所以二级transactional缓存的代理未真正缓存
        student = sqlSession.selectOne("selectByKey", id);
        System.out.println(student.getId());
        System.out.println(student.getStudentName());

        // local cache hit
        // 由于二级缓存未真正缓存,只能从一级缓存那里命中
        student = sqlSession.selectOne("selectByKey", id);
        System.out.println(student.getId());
        System.out.println(student.getStudentName());

        // commit
        sqlSession.commit();

        // sqlsession在commit之后,transactional缓存的代理才真正缓存起来,二级缓存命中
        student = sqlSession.selectOne("selectByKey", id);
        System.out.println(student.getId());
        System.out.println(student.getStudentName());

        // update 会clear未commit的transactional缓存中的内容,同时设置标志位clearOnCommit为true,会clear掉local cache
        student.setStudentName("Hunt");
        int update = sqlSession.update("updateByKey", student);
        System.out.println("update: " + update);

        // select again
        // 在二级缓存中找到了缓存,但是由于clearOnCommit标志位为true,所以返回null
        student = sqlSession.selectOne("selectByKey", id);
        System.out.println(student.getId());
        System.out.println(student.getStudentName());

        // commit & close
        sqlSession.commit();
        sqlSession.close();
    }

其中,二级缓存默认为:



6. References


深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇)
MyBatis 缓存
MyBatis 缓存机制深度解剖 / 自定义二级缓存
mybatis的缓存机制(一级缓存二级缓存和刷新缓存)和mybatis整合ehcache


Mybatis工作机制源码分析—缓存机制及事务机制

本文主要以源码分析的角度分析Mybatis的缓存工作机制及事务机制。 缓存工作机制 整体设计图          网上一张关于Mybatis的缓存工作机制示意图: Cache类结构图 ...

我对MyBatis的缓存机制的理解

MyBatis的缓存机制是基于ID进行缓存的,也就是说,MyBatis使用HashMap缓存数据时,是使用对象的ID作为key,而对象作为value保存的。 MyBatis的查询缓存分为一级缓存和二...
  • LYW_lyw
  • LYW_lyw
  • 2017年06月23日 10:37
  • 300

MyBatis 缓存机制

原文连接: 缓存概述  正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持;一级缓存基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为...

MyBatis(三) 事务管理和缓存机制

一、事务管理 1.1 Transaction接口 1、构成: (1)MyBatis的事务设计重点是Transaction接口,Transaction接口有两个实现类,分别是 JdbcTransa...

MyBatis缓存机制学习笔记

与Hibernate一样,MyBatis 同样提供了一级缓存和二级缓存的支持。 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 ...
  • canot
  • canot
  • 2016年05月24日 16:58
  • 6180

MyBatis框架的二级缓存机制(mapper级别)

代码: User.java package com.bean; import java.io.Serializable; public class User implements Serial...

MyBatis 缓存机制

MyBatis 提供了查询缓存来缓存数据,以提高查询的性能。MyBatis 的缓存分为一级缓存和二级缓存。 一级缓存是 SqlSession 级别的缓存 二级缓存是 mapper 级别的缓存,多个 ...

MyBatis缓存机制

缓存机制是为了减轻数据库压力,提高数据库性能。 Mybatis查询缓存分为一级缓存和二级缓存,默认开启一级缓存。...
  • gxing19
  • gxing19
  • 2017年04月30日 14:39
  • 156

MyBatis 缓存机制深度解剖

缓存概述  正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持;一级缓存基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Sess...
  • novelly
  • novelly
  • 2014年03月20日 20:16
  • 714

MyBatis缓存机制的设计与实现

本文主要讲解MyBatis非常棒的缓存机制的设计原理,给读者们介绍一下MyBatis的缓存机制的轮廓,然后会分别针对缓存机制中的方方面面展开讨论。 MyBatis将数据缓存设计成两级结构,分...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【MyBatis】mybatis执行流程与缓存机制分析
举报原因:
原因补充:

(最多只允许输入30个字)