范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Mybatis执行流程浅析(附深度文章推荐ampampamp面试题集锦)

  执行流程的理解
  理解 Mybatis 的简单流程后自己手写一个,可以解决百分之 70 的面试问题和开发中遇到的困惑,此乃重中之重
  假如我们要自己设计一个半自动的仿 Mybatis 框架,有哪些环节是必不可少的呢?思考再三,必然有以下环节:
  相关配置文件加载(XML 类型,接口类型则可以省略) 接口代理(JDK 动态代理) 针对 XML 或者接口进行解析 ==》即把`` 不可直接执行的SQL  ``处理为携带参数,返回值明确的数据结构 JDBC 模块执行,并返回对应的返回值类型
  如果仅考虑这三点的话,其实实现一个简单的 ORM 框架就很容易了,再附加一些反射和正则表达式等等就可以搞定了.
  那如果去参考 Mybatis,我们来看看它的几个环节是如何设计的:
  其实大致思路一样,需要一个数据结构去存储全部的变量,通过接口代理的方式调用 Sqlsession 里面内置的方法,`` 不同的是真正的执行者又加了一层,是 Executor  ``,再通过原始 JDBC 返回数据给调用者,当然, 真正的 Mybatis 包含了众多的设计模式以及数据源,缓存,动态 SQL,数据库事务,延迟加载处理 等等
  为了验证 mybatis 的执行流程,采用了两种方式去调用接口,如下所示: public static void main(String[] args) throws IOException {     // 指定全局配置文件     String resource = "mybatis-config.xml";      // 读取配置文件     InputStream inputStream = Resources.getResourceAsStream(resource);      // 构建sqlSessionFactory     SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);      SqlSession sqlSession = sqlSessionFactory.openSession();      // Mapper 编程方式     ScriptDirDao mapper = sqlSession.getMapper(ScriptDirDao.class);     System.out.println(mapper.selectOne(1));      // ibatis 编程方式 ---> 注意由于没有显式设置提交, 因此两个sql执行使用的是同一次sqlsession, 即默认触发了一级缓存     Object object = sqlSession.selectOne("com.mycode.mybatis.ScriptDirDao.selectOne", 1);     System.out.println(object); }
  ibatis 编程方式实际就是通过 namespace+方法名定位具体的接口方法,然后传递参数并执行
  >
  正常使用方式就是基于上述的基本流程做了一层自动的返回值映射,接口方法的匹配
  这里有个小点需要强调下,真正的执行者是`` Executor  ``,我们每次在使用以下代码: // 构建sqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);  SqlSession sqlSession = sqlSessionFactory.openSession();  // Mapper 编程方式 ScriptDirDao mapper = sqlSession.getMapper(ScriptDirDao.class); System.out.println(mapper.selectOne(1));
  通过查看源码也可以看到,SqlSession 接口的默认实现类是`` DefaultSqlSession  `` public class DefaultSqlSession implements SqlSession {    private final Configuration configuration;   private final Executor executor;  // 执行者    private final boolean autoCommit;   private boolean dirty;   private List> cursorList;   ....... }
  而方法真正的执行,如 selectList 方法: @Override public  List selectList(String statement, Object parameter, RowBounds rowBounds) {     try {         MappedStatement ms = configuration.getMappedStatement(statement);         return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);     } catch (Exception e) {         throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);     } finally {         ErrorContext.instance().reset();     } }面试题集锦
  Myabtis 的细节使用和执行原理其实都很好理解,对于源码感兴趣的可以深挖,但大多时候建议点到为止即可
  >
  还是着眼当下 面向面试要点进行针对性学习( 不包括一些简单的使用问题 )
  #{}和 ${}的区别是什么?
  #{} 是预编译处理,${}是字符串替换。Mybatis 在处理 #{}时,会将 sql 中的 #{}替换为?号,调用 PreparedStatement 的
  set 方法来赋值;
  Mybatis 在处理时,就是把时,就是把{}替换成变量的值。
  使用 #{}可以有效的防止 SQL 注入,提高系统安全性
  PS:mybatis 执行的本质还是 SQL,因此回归本质可以简单理解为一个对于 PreparedStatement ,一个对应 Statement
  通常一个 Xml 映射文件,都会写一个 Dao 接口与之对应,请问,这个 Dao 接口的工作原理是什么?Dao 接口里的方法,参数不同时,方法能重载吗?(id 是否可以相同)
  Dao 接口即 Mapper 接口,接口的全限名,就是映射文件中的 namespace 的值;接口的方法名,就是映射文件中 Mapper 的 Statement 的 id 值;接口方法内的参数,就是传递给 sql 的参数
  ``实现原理: `Mapper接口的工作原理是JDK动态代理,mybatis会对每一个mapper代理生成一个mapperProxy对象,代理对象会拦截接口方法,转而自动对应到sqlsession上,最终由 `Executor ``执行
  ``参数不同,方法不可重载 ``,为什么?
  上文说到 mybatis 有一个环节是解析 XML 文件或者解析接口,它会去构建一个叫做 MapperStatement 对象去存储 mapper 的相关信息,每一个 dao 接口方法在执行的时候到底是如何定位找到对应的 MapperStatement 的呢?
  源码逻辑图:
  // 这个 mappedStatements 即 protected final Map mappedStatements = new StrictMap("Mapped Statements collection");  // Key即 XML文件中配置的