JavaWeb编程面试题——MyBatis

引言

面试题==知识点,这里所记录的面试题并不针对于面试者,而是将这些面试题作为技能知识点来看待。不以刷题进大厂为目的,而是以学习为目的。这里的知识点会持续更新,目录也会随时进行调整。

关注公众号:编程火箭车。在【粉丝福利】中点击【面题大全】,其中的Java面试题在线实时更新、查看。


一、面试题导航

点这里进入JavaWeb编程面试题——导航

面试题持续更新中......

二、面试题目

1.什么是MyBatis?

(1)MyBatis 是一个半 ORM(对象关系映射)框架,它内部封装了 JDBC,开发时只需关注 SQL 语句本身,不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。程序员直接编写原生态 SQL,可以严格控制 SQL 执行性能,灵活度高。

(2)MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO 映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。

(3)通过 XML 文件或注解的方式将要执行的各种 statement 配置起来,并通过 Java 对象和 statement 中 SQL 的动态参数进行映射生成最终执行的 SQL 语句,最后由 MyBatis 框架执行 SQL 并将结果映射为 Java 对象并返回。(从执行 SQL 到返回 result 的过程)

2.MyBatis优缺点?

优点:
(1)基于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL 写在 XML 中,解除 SQL 与程序代码的耦合,便于统一管理。提供 XML 标签,支持编写动态 SQL 语句,并可重用;

(2)与 JDBC 相比,减少了50%以上的代码量,消除了 JDBC 大量冗余的代码,不需要手动开关连接;

(3)很好的与各种数据库兼容(因为 MyBatis 使用 JDBC 来连接数据库,所以只要 JDBC 支持的数据库 MyBatis 都支持);

(4)能够与 Spring 很好的集成(MyBatis 官方提供与 Spring 的整合包);

(5)提供映射标签,支持对象与数据库的 ORM 字段关系映射;提供对象关系映射标签,支持对象关系组件维护。

缺点:

(1)SQL 语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写 SQL 语句的功底有一定要求。

(2)SQL 语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

3.MyBatis框架适用场合?

MyBatis 专注于 SQL 自身,是一个足够灵活的 DAO 层解决方案。对性能的要求很高,或者需求变化较多的项目,例如 Web 项目,互联网项目等等, MyBatis 都是不错的选择。

4.MyBatis框架原理?

mybatis架构图

  1. MyBatis 配置:SqlMapConfig.xml,此文件作为 MyBatis 的全局配置文件,配置了 MyBatis 的运行环境等信息。mapper.xml 文件即 SQL 映射文件,文件中配置了操作数据库的 SQL 语句。此文件需要在 SqlMapConfig.xml 中加载。

  2. 通过 MyBatis 环境等配置信息构造 SqlSessionFactory 即会话工厂。

  3. 由会话工厂创建 sqlSession 即会话,操作数据库需要通过 sqlSession 进行。

  4. MyBatis 底层自定义了 Executor 执行器接口操作数据库,Executor 接口有两个实现,一个是基本执行器、一个是缓存执行器。

  5. Mapped Statement 也是 MyBatis 一个底层封装对象,它包装了 MyBatis 配置信息及 SQL 映射信息等。mapper.xml 文件中一个 SQL 对应一个 Mapped Statement 对象,SQL 的 id 即是 Mapped statement 的 id。

  6. Mapped Statement 对 SQL 执行输入参数进行定义,包括 HashMap、基本类型、POJO,Executor 通过 Mapped Statement 在执行 SQL 前将输入的 Java 对象映射至 SQL 中,输入参数映射就是 JDBC 编程中对 preparedStatement 设置参数。

  7. Mapped Statement 对 SQL 执行输出结果进行定义,包括 HashMap、基本类型、POJO,Executor 通过 Mapped Statement 在执行 SQL 后将输出结果映射至 Java 对象中,输出结果映射过程相当于 JDBC 编程中对结果的解析处理过程。

5.MyBatis和Hibernate的区别?

(1)MyBatis 和 Hibernate 不同,它不是一个完全的 ORM 框架,因为 MyBatis 需要程序员自己编写 SQL 语句;

(2)MyBatis 直接编写原生态 SQL,可以严格控制 SQL 执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,因为这类软件需求变化频繁,一旦有需求变化可以迅速输出成果。但是灵活的前提是 MyBatis 无法做到数据库无关性,如果需要实现支持多种数据库的软件,则需要自定义多套 SQL 映射文件,工作量大。

(3)Hibernate 对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件,如果用 Hibernate 开发可以节省很多代码,提高效率。

6.MyBatis有哪些动态标签?

  • if 标签:判断是否符合条件

  • foreach 标签:对一个集合进行遍历

  • where 标签:补充响应的 where 的 SQL 语句

  • sql 标签:定义可重用的 SQL 代码段,可以包含在其他语句中。

  • ......

7.MyBatis中一对一如何实现?

在映射文件中 resultMap 元素里配置 association 节点,配置一对一的类就可以完成。

8.MyBatis中一对多如何实现?

在映射文件中 resultMap 里面配置 collection 节点,配置一对多的类就可以完成。

9.MyBatis编程步骤?

  1. 创建 SqlSessionFactory 会话工厂

  2. 通过 SqlSessionFactory 创建 SqlSession 会话

  3. 通过 sqlSession 执行数据库操作

  4. 通过 `session.commit()`` 提交事务

  5. 调用 `session.close()`` 关闭会话

10.MyBatis的一级缓存和二级缓存?

  • Mybatis 首先会到缓存中查询结果集,如果没有则查询数据库,如果有则直接从缓存取出结果集。Mybatis 内部存储缓存使用一个 HashMap,key 为 hashCode+sqlId+Sql 语句。value 为从查询出来映射生成的 Java 对象。

  • Mybatis 的一级缓存即本地缓存,它的作用域是一个 sqlSession 会话,即在同一个 sqlSession 中两次执行相同的 SQL 语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。

  • Mybatis 的二级缓存即查询缓存,它的作用域是一个 mapper 的 namespace,即在同一个 namespace 中查询相同的 SQL 可以从缓存中获取数据。二级缓存是可以跨 SqlSession 的。

11.#{} 和 ${} 区别?

  • #{}表示一个占位符号,可以有效防止sql注入。

  • ${}表示拼接sql串,在低版本中括号中只能是value。

  • #{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。

  • #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。

  • ${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换。

  • ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,低版本中${}括号中只能是value。

12.Mybatis的mapper.xml文件中常用标签有哪些?

<select>、<insert>、<update>、<delete>、<sql>、<resultMap>、<set>、<where>...

13.Mybatis的xml映射文件中,不同的xml映射文件,id是否可以重复?

不同的xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复;原因就是namespace+id是作为Map<String, MapperStatement>的key使用的,如果没有namespace,就剩下id,那么,id重复会导致数据互相覆盖。有了namespace,自然id就可以重复,namespace不同,namespace+id自然也就不同。

备注:在旧版本的Mybatis中,namespace是可选的,不过新版本的namespace已经是必须的了。

14.MyBatis 分页如何处理?

mybatis分页查询有两种方案:

  • 可以通过limit关键字拼接SQL语句,需要两个参数,第一个参数为开始条数,第二个参数为查询个数。

  • 可以通过 pageHelper 插件实现:

    • 在sqlMapConfig 文件中配置 mybatis的插件(plugins)

    • 在查询数据前通过 PageHelper.start() 方法,调用 PageHelper 插件,参数为当前页和每页显示条数

    • 查询结果会封装到一个page对象中,包含分页查询记录、总记录数、总页数等

    • 从page对象中获取需要的数据

15.Mybatis是如何进行分页的?分页插件的原理是什么?

Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。

分页插件的基本原理是使用mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

16.如何获取自动生成的主键?

  • 自增主键返回

    • mysql 自增主键,执行 insert 提交之前自动生成一个自增主键。可以通过 mysql 函数获取刚插入记录的自增主键:LAST_INSERT_ID(),是在insert之后去调用。

      <insert id="insertTeacher" parameterType="Teacher" >
      	<selectKey keyProperty="id" resultType="java.lang.Integer" order="AFTER">
      		SELECT LAST_INSERT_ID()
      	</selectKey>
      	INSERT INTO teacher (name,idcard,sex) VALUES (#{name},#{idcard},#{sex})
      </insert>
      
    • 设置insert属性获取自增id

      <insert id="insertTeacher" parameterType="Teacher" useGeneratedKeys="true" keyProperty="id" >
      	INSERT INTO teacher (name,idcard,sex) VALUES (#{name},#{idcard},#{sex})
      </insert>
      
  • 非自增主键返回

    mysql 使用 uuid 实现主键,需要修改表中 id 字段类型为 varchar,长度至少36位。
    执行思路:先通过 uuid() 查询到主键,将主键输入到 SQL 语句中。执行 uuid() 语句顺序相对于 insert语句在之前。

    <!-- 使用mysql的uuid()生成主键
    	执行过程:
    	首先通过uuid()得到主键,将主键设置到teacher对象的id属性中
    	其次在insert执行时,从teacher对象中取出id属性值
    -->
    <insert id="insertTeacher" parameterType="Teacher">
    	<selectKey keyProperty="id" resultType="java.lang.String" order="BEFORE">
    		SELECT UUID()
    	</selectKey>
    	INSERT INTO teacher (id,name,idcard) VALUES (#{id},#{name},#{idcard})
    </insert>
    

17.在mapper中如何传递多个参数?

第一种:直接多个参数

// DAO层 接口
User listUsers(String name, String sex);
<!-- mapper映射文件 
		#{0}代表接收dao层方法中的第一个参数,#{1}代表接收第二个参数,更多参数一直往后加即可
-->
<select id="listUsers" resulType="User">
    select * from user where name=#{0} and sex=#{1}
</select>

第二种:使用@param注解

// DAO层 接口
User listUsers(@param("uname") String name, @param("usex") String sex);
<!-- mapper映射文件 -->
<select id="listUsers" resulType="User">
    select * from user where name=#{uname} and sex=#{usex}
</select>

第三种:多个参数封装成map集合

// 映射文件的命名空间.sql片段的id,就可以调用对应的映射文件的SQL
// 由于参数超过了两个,而方法中只有一个Object参数收集,因此我们使用Map集合来封装参数
Map<String, Object> map = new HashMap<>();
map.put("uname", "张三");
map.put("usex", "男");

sqlSession.selectList("user.listUsers", map);
<!-- mapper映射文件 -->
<select id="listUsers" resulType="User">
    select * from user where name=#{uname} and sex=#{usex}
</select>

18.使用mapper接口开发DAO时有哪些要求?

  • Mapper.xml 文件中的 namespace 与 mapper 接口的类路径相同。

  • Mapper 接口方法名和 Mapper.xml 中定义的每个 statement 的 id 相同

  • Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的 parameterType 的类型相同

  • Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的 resultType 的类型相同

19.MyBatis的配置文件sqlMapConfig.xml中有哪些内容?

配置内容和顺序如下:

  • configuration(配置)
    • properties(属性)
    • settings(全局配置参数)
    • typeAliases(类型别名)
    • typeHandlers(类型处理器)
    • objectFactory(对象工厂)
    • plugins(插件)
    • environments(环境配置)
    • environment(环境变量)
    • transactionManager(事务管理器)
    • dataSource(数据源)
    • databaseIdProvider(数据库厂商标识)
    • mappers(映射器)

20.MyBatis中有哪些重要组件?

MyBatis是一个开源的Java持久化框架,它可以轻松访问关系数据库,将SQL语句和数据映射到Java对象中,并提供了很多高级特性。下面是MyBatis中的几个重要组件:

  1. SqlSession:SqlSession是MyBatis的核心接口之一,其作用相当于对JDBC操作的封装。SqlSession提供了执行SQL语句、提交事务、获取Mapper映射器等操作。

  2. Configuration:Configuration是MyBatis的全局配置类,它负责解析和管理MyBatis的配置文件,并提供了许多高级特性,如缓存配置、类型别名配置、插件配置等。

  3. Mapper映射器:Mapper映射器是MyBatis中用于映射Java方法与SQL语句的方法。通过Mapper映射器,可以将Java方法和SQL语句绑定在一起,从而轻松地在Java中执行SQL语句。

  4. Executor:Executor是MyBatis中用于执行SQL语句的核心接口,它负责从SqlSession中接收SQL语句并执行它们,同时还负责缓存结果、处理事务等操作。

  5. TypeHandler:TypeHandler是MyBatis中的重要组件之一。它负责将Java对象和数据库中的数据进行转换。MyBatis中默认提供了很多TypeHandler,同时也支持自定义TypeHandler。

这些组件构成了MyBatis框架的核心,并提供了许多高效、易用、可扩展的特性,使开发人员可以轻松地进行数据访问和持久化操作。


关注公众号:编程火箭车
我们定期发布编程相关的文章、资讯、活动等内容。帮助编程爱好者、初学者或初级程序员快速入门、打牢基础。欢迎大家关注,和我们一起探索编程的精彩世界。

posted @ 2023-05-29 11:25  编程火箭车  阅读(173)  评论(0编辑  收藏  举报