文章目录
代码中的两行代码是如何执行的?
java
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
userMapper.selectById(userId);
第一行:
获取 Mapper 接口的代理对象,调用链如下:
java
SqlSession.getMapper()
→ Configuration.getMapper()
→ MapperRegistry.getMapper() // 使用map做了缓存,若没有则继续向下
→ MapperProxyFactory.newInstance() // 使用 JDK 动态代理生成 Mapper 接口的代理对象。即返回的是一个动态生成代理类对象。具体的代理过程此处不详细介绍,在后文。
第二行:
执行SQL:动态代理拦截方法调用。
userMapper.selectById(userId);
上述得知userMapper对象是代理类对象,此处调用的selectById
方法就是代理类中实现的接口方法(当然不是具体的实现内容,具体的实现内容在InvocationHandler与JDK动态代理相关)参考JDK动态代理
java
// 例如:执行userMapper.selectUserById(1);
MapperProxy.invoke() // MapperProxy 就是InvocationHandler的实现,即具体实现内容在此。在调用链中还涉及到二级缓存的事情,后续说明
→ MapperMethod.execute() // MapperMethod 将方法调用转为SqlSession的操作,如selectOne/insert等
→ SqlSession.selectOne()
→ Executor.query() // 有多种执行器,后续详细说明
→ MappedStatement.getBoundSql()
→ query() // 此处涉及到一级缓存的事情,后续说明;如果没有命中一级缓存,则查询数据库
→ Executor.prepareStatement() // 此处涉及到TypeHandler,将对应的java数据转化为sql类型的数据
→ StatementHandler.query()
→ PreparedStatement.execute() // 执行sql
→ ResultHandler.handleResultSets() // 此处涉及到TypeHandler,将结果集转化为java类型的数据
Client SqlSession MapperProxy MapperMethod Executor JDBC getMapper(UserMapper.class) 创建动态代理 userMapper.selectUserById(1) 解析方法调用 selectOne("selectUserById", 1) query() 执行 SQL 返回 ResultSet 转换为 User 对象 返回结果 Client SqlSession MapperProxy MapperMethod Executor JDBC
相关内容:
JDK代理
Mybatis加载Mapper
MapperRegistry
MyBatis中JDK动态代理
Mybatis之MapperProxy
Mybatis之MapperMethod
Mybatis之Executor执行器
Mybatis之StatementHandler
Mybatis之KeyGenerator