【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




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)



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;
  }





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




Hibernate缓存机制和MyBatis缓存机制

原文地址:https://my.oschina.net/u/1445731/blog/416200?p=%7B%7BtotalPage%7D%7D 摘要: mybatis缓存分为1级缓存和2级缓存 ...
  • tanga842428
  • tanga842428
  • 2016年09月29日 09:42
  • 9784

Mybatis缓存机制深入解析

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

《深入理解mybatis原理》 MyBatis缓存机制的设计与实现

本文主要讲解MyBatis非常棒的缓存机制的设计原理,给读者们介绍一下MyBatis的缓存机制的轮廓,然后会分别针对缓存机制中的方方面面展开讨论。...
  • u010349169
  • u010349169
  • 2014年11月23日 13:57
  • 37767

深入理解mybatis原理(五) MyBatis缓存机制的设计与实现

本文主要讲解MyBatis非常棒的缓存机制的设计原理,给读者们介绍一下MyBatis的缓存机制的轮廓,然后会分别针对缓存机制中的方方面面展开讨论。 MyBatis将数据缓存设计成两级结构,分...
  • z742182637
  • z742182637
  • 2017年05月20日 10:07
  • 624

hibernate和mybatis缓存的对比

Mybatis缓存 分为1级缓存和2级缓存,2级缓存在sessionfactory中,1级缓存在session中。 session中的缓存在session连接关闭并被连接池回收时清...
  • Tidhy
  • Tidhy
  • 2017年06月02日 16:01
  • 1051

细说mybatis的缓存机制

和其他持久层框架一样,mybatis也提供了对缓存的支持--一级缓存和二级缓存; 一、缓存介绍 一级缓存:基于PerpetualCache的HashMap的本地缓存,一级缓存的作用域为sqlSessi...
  • YSC1123
  • YSC1123
  • 2016年03月07日 17:00
  • 1540

mybatis缓存机制与hibernate缓存机制

mybatis缓存分为1级缓存和2级缓存,2级缓存在sessionfactory中,1级缓存在session中。 session中的缓存在session连接关闭并被连接池回收时清理,或者手动清理 ...
  • u014756827
  • u014756827
  • 2016年10月08日 10:59
  • 809

mybatis工作原理&执行流程

mybatis工作原理&执行流程 MyBatis的框架架构                     看到Mybatis的框架图,可以清晰的看到Mybatis的整体核心对象,我更喜欢用自己的图...
  • merrylilili
  • merrylilili
  • 2016年11月01日 20:51
  • 10186

【mybatis】mybatis产生过程和执行流程

产生必然性传统的JDBC的实现方式,存在太多的硬编码方式,包括对数据库的管理,sql语句的编写,参数和返回值等,这种现象很难应对多变化的需求开发。 这个时候,mybatis产生了。mybatis主要针...
  • wangyy130
  • wangyy130
  • 2016年06月14日 19:52
  • 4399

我对MyBatis的缓存机制的理解

MyBatis的缓存机制是基于ID进行缓存的,也就是说,MyBatis使用HashMap缓存数据时,是使用对象的ID作为key,而对象作为value保存的。 MyBatis的查询缓存分为一级缓存和二...
  • LYW_lyw
  • LYW_lyw
  • 2017年06月23日 10:37
  • 375
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【MyBatis】mybatis执行流程与缓存机制分析
举报原因:
原因补充:

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