Mybatis面试题

Mybatis

MyBatis是什么

Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,加载驱动、创建连接、创建statement等繁杂的过程,开发者开发时只需要关注如何编写SQL语句,可以严格控制sql执行性能,灵活度高

作为一个半ORM框架,MyBatis 可以使用 XML 或注解来配置和映射原生信息

为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?

Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的

而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。Mybatis 直接编写原生态 sql,可以严格控制 sql 执行性能,灵活度高

mongodb 中的 mongoose,也算是一个全自动 ORM,需要定义 Schema 和 Model

JDBC编程有哪些不足之处,MyBatis是如何解决这些问题的

1、SQL 语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。

解决:将SQL语句配置在XXXXmapper.xml文件中与java代码分离

2、 向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应

解决: Mybatis自动将java对象映射至sql语句

3、 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便

解决:Mybatis自动将sql执行结果映射至java对象

MyBatis编程步骤是什么样的?

  1. 创建 UserMapper.xml SQL 映射文件 和 UserMapper.java 接口类
  2. 创建 SqlSessionFactory
  3. 通过 SqlSessionFactory 创建 SqlSession
  4. 通过 SqlSession 获取 mapper
  5. 通过 mapper 执行数据库操作
  6. 调用 session.commit() 提交事务
  7. 调用 session.close() 关闭会话

#{}和${}的区别

#{}:占位符,被替换为 ?,相当于用 JDBC中的 PerparedStatement 的 set 方法赋值,能够防止 SQL 注入

?{}:拼接符,字符串替换,相当于 JDBC 中的 Statement,没有预编译处理,存在 SQL 注入的风险

Dao接口的工作原理是什么?能重载接口中的方法吗

Dao接口即Mapper接口。接口的全类名就是映射文件中的 namespace 的值
接口的方法名,就是映射文件中Mapper的Statement的id值
接口方法内的参数,就是传递给sql的参数
Mapper接口是没有实现类的,当调用接口方法时,接口全类名+方法名的拼接字符串作为key值,可唯一定位一个MapperStatement

Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略

Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回

Mybatis动态sql是做什么的?都有哪些动态sql

Mybatis动态sql可以在xml映射文件内,以标签的形式编写动态sql,执行原理是根据表达式的值完成逻辑判断,并动态拼接sql的功能

Mybatis提供了9种动态sql标签:where、set、foreach、if、choose、when、otherwise

    <select id="selectByCondition" resultMap="brandResultMap">
        select *
        from tb_brand
        <where>
            <if test="status != null">
                and status = #{status}
            </if>
            <if test="companyName != null and companyName != '' ">
                and company_name like #{companyName}
            </if>
            <if test="brandName != null and brandName != '' ">
                and brand_name like #{brandName}
            </if>
        </where>
    </select>

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

不同的xml映射文件,如果配置了namespace,那么id可以重复

如果没有配置namespace,那么id不能重复

原因是 namespace+id 是作为 Map<String,MapperStatement> 的key使用的

使用MyBatis的Mapper接口调用时有哪些要求?

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

在Mapper中如何传递多个参数

1、使用@Param注解:在Dao层的参数中前加@Param注解,注解内的参数名为传递到Mapper中的参数名
2、多个参数封装成Map,以HashMap的形式传递到Mapper中
3、实体类对象传参

    <select id="selectById" resultMap="brandResultMap">
        select * from tb_brand where id=#{id}
    </select>
Brand selectById(int id);
    <select id="selectByCondition" resultMap="brandResultMap">
        select *
        from tb_brand
        where
            status = #{status}
        and company_name like #{companyName}
        and brand_name like #{brandName}
    </select>
List<Brand> selectByCondition(@Param("status")int status, @Param("companyName")String companyName, @Param("brandName")String brandName);
List<Brand> selectByCondition(Brand brand);
List<Brand> selectByCondition(Map map);

MyBatis 的执行流程

首先加载 mybatis-config.xml 映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <typeAliases>
        <package name="com.itheima.pojo"/>
    </typeAliases>
    
    <!--
    environments:配置数据库连接环境信息。可以配置多个environment,通过default属性切换不同的environment
    -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--数据库连接信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://192.168.93.12/itcast?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value=""/>
            </dataSource>
        </environment>
    </environments>
    
    <mappers>
        <!--加载sql映射文件-->
       <mapper resource="UserMapper.xml"/>
    </mappers>
    
</configuration>

在这里插入图片描述

Mybatis是否支持延迟加载

支持,但是默认没有开启

什么叫延迟加载:

在这里插入图片描述
如果不在业务代码中调用 user.getOrderList(),就不会去查询订单表

局部开启延迟加载:在 resultMap 标签中设置 fetchType 属性

<resultMap>
	<collection property="orderList" ofType="order" select="" fetchType="lazy"></collection>
</resultMap>

全局开启延迟加载:在 mybatis-config.xml 配置文件中的 settings 标签中增加对应的配置:

<settings>
	<setting name="lazyLoadingEnabled" value="true">
</settings>

MyBatis 的一级和二级缓存

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1,对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了新增、修改、删除操作后,默认该作用域下所有 select 中的缓存将被 clear
2,二级缓存需要缓存的数据实现Serializable接口
3,只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中

相关推荐

  1. 面试(三)mybatis

    2024-06-11 10:34:03       33 阅读
  2. Mybatis学习&面试

    2024-06-11 10:34:03       15 阅读
  3. MyBatis 面试(八)

    2024-06-11 10:34:03       14 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-11 10:34:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-11 10:34:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-11 10:34:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-11 10:34:03       18 阅读

热门阅读

  1. SQL的执行顺序

    2024-06-11 10:34:03       7 阅读
  2. Web前端与PHP:深度解析与未来展望

    2024-06-11 10:34:03       10 阅读
  3. 特别名词Test Paper3

    2024-06-11 10:34:03       9 阅读
  4. 微信小程序真机调试连不上

    2024-06-11 10:34:03       7 阅读
  5. MATLAB 论文绘图规范标注

    2024-06-11 10:34:03       11 阅读
  6. 模块间通信

    2024-06-11 10:34:03       7 阅读
  7. 后端|压缩Base64图片的两种方式

    2024-06-11 10:34:03       8 阅读