首页 > 技术文章 > 【Java面试题】Mybatis

rainbow-1 2022-05-27 18:30 原文

五、MyBatis

40)谈谈 MyBatis

Mybatis 是一个半自动化的 ORM 框架,它对 jdbc 的操作数据库的过程进行封装,使得开发者只需要专注于 SQL 语句本身,而不用去关心注册驱动,创建 connection 等,Mybatis 通过 xml 文件配置或者注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中的sql 进行映射成最终执行的 sql 语句,最后由 Mybatis 框架执行 sql 并将结果映射成 java 对象并返回。每个 MyBatis 应用程序主要都是使用 SqlSessionFactory 实例的,一个 SqlSessionFactory 实例可以通过 SqlSessionFactoryBuilder 获得。SqlSessionFactoryBuilder 可以从一个 xml 配置文件或者一个预定义的配置类的实例获得。
Mybatis 分为三层
(1) API 接口层:提供给外部使用的接口 API
(2) 数据处理层:负责具体的 SQL
(3) 基础支撑层:负责最基础的功能支撑,如连接管理,事务管理,配置加载和缓存处。理

41)Mybatis 的优点

  • 基于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL 写在 XML 里,解除 sql 与程序代码的耦合,便于统一管理;提供 XML 标签,支持编写动态 SQL 语句,并可重用。
  • 与 JDBC 相比,减少了 50%以上的代码量,消除了 JDBC 大量冗余的代码,不需要手动开关连接;
  • 很好的与各种数据库兼容(因为 MyBatis 使用 JDBC 来连接数据库,所以只要 JDBC 支持的数据库 MyBatis 都支持)。
    能够与 Spring 很好的集成;
  • 提供映射标签,支持对象与数据库的 ORM 字段关系映射;提供对象关系映射标签,支持对象关系组件维护。

42)Mybatis 的优点

  1. Sql 语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写 Sql 语句的功底有一定要求。
  2. 对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis 将是不错的选择。

43)Mybatis 的编程过程是怎样的

  1. 创建 SqlSessionFactory
  2. 通过 SqlSessionFactory 创建 SqlSession
  3. 通过 sqlsession 执行数据库操作
  4. 调用 sqlsession.commit()提交事务
  5. 调用 sqlsession.close()关闭会话

44)Mybatis 中#和$的区别?

  1. ${}是 Properties 文件中的变量占位符,它可以用于标签属性值和 sql 内部,属于静态文本替换

  2. {}是 sql 的参数占位符,Mybatis 会将 sql 中的#{}替换为?号,在 sql 执行前会使用PreparedStatement 的参数设置方法,按序给 sql 的? 号占位符设置参数值。

  3. 方式能够很大程度防止 sql 注入。

    $方式无法防止 Sql 注入。
    $方式一般用于传入数据库对象,例如传入表名。

  4. 为什么 # 可以防止SQL注入?参考作者:https://www.cnblogs.com/coder-who/

    • 1.什么是SQL注入

      答:SQL注入是通过把SQL命令插入到web表单提交或通过页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL指令。

        注入攻击的本质是把用户输入的数据当做代码执行。

        举例如: 表单有两个用户需要填写的表单数据,用户名和密码,如果用户输入admin(用户名),111(密码),若数据库中存在此用户则登录成功。SQL大概是这样

            SELECT * FROM XXX WHERE userName = admin and password = 111

           但若是遭到了SQL注入,输入的数据变为 admin or 1 =1 # 密码随便输入,这时候就直接登录了,SQL大概是这样

            SELECT * FROM XXX WHERE userName = admin or 1 = 1 # and password = 111 ,因为 # 在sql语句中是注释,将后面密码的验证去掉了,而前面的条件中1 = 1始终成立,所以不管密码正确与否,都能登录成功。

      2.mybatis中的#{} 为什么能防止sql注入,${}不能防止sql注入

      答: #{}在mybatis中的底层是运用了PreparedStatement 预编译,传入的参数会以 ? 形式显示,因为sql的输入只有在sql编译的时候起作用,当sql预编译完后,传入的参数就仅仅是参数,不会参与sql语句的生成,而${}则没有使用预编译,传入的参数直接和sql进行拼接,由此会产生sql注入的漏洞。

    • 再次理解sql预编译前后传参数的区别?参考作者:https://blog.csdn.net/weixin_46099269

      • select * from user where uid=#{id} and password=#{pwd};
        这时数据库就会进行预编译,并进行一个缓存动作,缓存一条这样的语句:
        select * from user where uid=? and password=?;
        当我们调用这条语句,并实际向#{id}中的id传了一个值 “deftiii” or 1=1# 时,不需要在编译,数据库会直接找对应的表中有没有名字是 “deftiii” or 1=1# 的用户,而不再有编译sql语句的过程。

45)使用 MyBatis 的 mapper 接口调用时有哪些要求?

  • Mapper接口方法名和 mapper.xml 中定义的每个 sql 的 id 相同
  • Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的 parameterType 的类型相同
  • Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的 resultType 的类型相同
  • Mapper.xml 文件中的 namespace 即是 mapper 接口的类路径

46)简述 Mybatis 的 Xml 映射文件和 Mybatis 内部数据结构间的映射关系?

  • Mybatis 将所有 Xml 配置信息都封装到 All-In-One 重量级对象 Configuration 内部。
  • 标签会被解析为 ParameterMap 对象,其每个子元素会被解析为ParameterMapping 对象。
  • 标签会被解析为 ResultMap 对象,其每个子元素会被解析为ResultMapping 对象。
  • 每一个

推荐阅读