MyBatis 面试专题

news2025/4/21 10:50:17

csdn

MyBatis 面试专题

  • 基础概念
    • MyBatis中的工作原理
    • MyBatis 与 Hibernate 的区别?
    • #{} 和 ${} 的区别?
    • MyBatis 的核心组件有哪些?
  • 映射与配置
    • 如何传递多个参数?
    • ResultMap 的作用是什么?
    • 动态 SQL 常用标签有哪些?
    • 如何复用 SQL 片段?
    • 当实体中的属性和表中的字段不一致的情况下怎么办?
  • 高级特性
    • 一级缓存与二级缓存的区别?
    • MyBatis中如何实现缓存的扩展
    • 如何实现延迟加载(懒加载)?
    • MyBatis 插件(Plugin)原理?
    • 分页插件的实现原理?
  • 关联查询
    • 一对一查询如何配置?
    • 一对多查询如何配置?
    • 嵌套查询 vs 嵌套结果的区别?
  • 事务与性能
    • MyBatis 如何管理事务?
    • 如何执行批量操作?
  • 常见问题排查
    • 如何防止SQL注入
    • Mapper 接口如何绑定到 XML?
    • 如何获取自动生成的主键?
    • 遇到 BindingException 可能的原因?
  • 扩展与集成
    • 如何与 Spring 集成?
    • MyBatis 如何整合分布式缓存(如 Redis)?

基础概念

MyBatis中的工作原理

  • 系统启动的时候会加载解析全局配置文件和对应映射文件。加载解析的相关信息存储在 Configuration对象
    @Test
    public void test1() throws Exception{
    // 1.获取配置文件
    InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
    // 2.加载解析配置文件并获取SqlSessionFactory对象
    // SqlSessionFactory 的实例我们没有通过 DefaultSqlSessionFactory直接来获取
    // 而是通过一个Builder对象来建造的
    // SqlSessionFactory 生产 SqlSession 对象的 SqlSessionFactory 应该是单例
    // 全局配置文件和映射文件 也只需要在 系统启动的时候完成加载操作
    // 通过建造者模式来 构建复杂的对象 1.完成配置文件的加载解析 2.完成
    SqlSessionFactory的创建
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
    // 3.根据SqlSessionFactory对象获取SqlSession对象
    SqlSession sqlSession = factory.openSession();
    // 4.通过SqlSession中提供的 API方法来操作数据库
    List<User> list =
    sqlSession.selectList("com.boge.mapper.UserMapper.selectUserList");
    // 获取接口的代码对象 得到的其实是 通过JDBC代理模式获取的一个代理对象
    // UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    //List<User> list = mapper.selectUserList();
    System.out.println("list.size() = " + list.size());
    // 5.关闭会话
    sqlSession.close(); // 关闭session 清空一级缓存
    }
    
  • SqlSessionFactory: new DefaultSqlSessionFactory 全局配置文件的加载解析【Configuration】,映射文件的加载解析【Configuration,MappedStatement】
  • SqlSession:new DefaultSqlSession,创建相关的事务工厂,完成Executor的创建,已经二级缓存CachingExecutor的装饰,同时完成了插件逻辑的植入。
  • selectOne(); 二级缓存 -> 一级缓存 --> 数据库插入。
  • SqlSession.getMapper()。
    mybatis
    源码结构
    resource

MyBatis 与 Hibernate 的区别?

  • MyBatis:半自动 ORM,需手动编写 SQL,灵活性高,适合复杂查询或对 SQL 优化有要求的场景。
  • Hibernate:全自动 ORM,通过 HQL 或 Criteria API 操作对象,适合快速开发简单 CRUD,但对复杂 SQL 支持较弱。

#{} 和 ${} 的区别?

  • #{}:预编译处理(占位符 ?),防止 SQL 注入,自动处理类型转换。
  • ${}:字符串替换(直接拼接 SQL),需手动防注入,常用于动态表名、列名等非参数场景。

MyBatis 的核心组件有哪些?

SqlSessionFactory(会话工厂)、SqlSession(会话)、Mapper 接口、Executor(执行器)、MappedStatement(SQL 映射)。

映射与配置

如何传递多个参数?

使用 @Param 注解标注参数名,或通过 POJO 对象、Map 封装参数。

ResultMap 的作用是什么?

解决数据库列名与 Java 对象属性名不一致的问题,支持复杂关联映射(一对一、一对多)。

动态 SQL 常用标签有哪些?

<if>、<choose>/<when>/<otherwise>、<foreach>、<where>、<set>、<trim>

<select id="queryPageAllEmployee" resultType="com.todaytech.salary.basicInfo.model.vo.EmployeeVO">
        SELECT * FROM (
        SELECT un.agency_name AS unit_name,un.mof_dep_code, d.dept_name AS dept_name, eunf.zj_tied_date, eunf.xs_retire_expert, ef.* ,eunf.stopsign
          FROM zz_employeefix ef
          LEFT JOIN zz_employeeunfix eunf ON ef.emp_id = eunf.emp_id
         INNER JOIN sys_agency un ON ef.unit_id = un.id
         INNER JOIN zz_department d ON (ef.unit_id = d.unit_id AND ef.dept_id = d.dept_id)
        <choose>
            <when test="salaryAgencyType != null and salaryAgencyType != ''">
                WHERE (ef.salary_agency_type = #{salaryAgencyType}
                <if test="childrenAgencyIds != null and childrenAgencyIds.size() > 0 ">
                    OR ef.unit_id IN <foreach collection="childrenAgencyIds" item="item" open="(" separator="," close=")"> #{item} </foreach>
                </if>)
            </when>
            <otherwise>
                <if test="childrenAgencyIds != null and childrenAgencyIds.size() > 0 ">
                    WHERE ef.unit_id IN <foreach collection="childrenAgencyIds" item="item" open="(" separator="," close=")"> #{item} </foreach>
                </if>
            </otherwise>
        </choose> ) em
        ${ew.customSqlSegment}
        ORDER BY emp_id DESC,emp_modified DESC
    </select>

如何复用 SQL 片段?

使用 <sql> 定义片段,通过 <include> 引用。

<sql id="getChildNotDeptSql">
    select orgclosure_id as id from sys_agency_relation where orgclosure_pid=#{agencyId}
</sql>
<select id="queryUnitIds" resultType="java.lang.Integer">
    select * from (
        <include refid="com.todaytech.vue.mapper.SysAgencyMapper.getChildNotDeptSql">
            <property name="agencyId" value="#{agencyId}"/>
        </include> ) ug
</select>

当实体中的属性和表中的字段不一致的情况下怎么办?

  • 我们可以在对应的SQL语句中通过别名的方式来解决这个问题。
  • 我们通过自定义resultMap标签来设置属性和字段的映射关系

高级特性

一级缓存与二级缓存的区别?

  • 缓存的作用:减低数据源的访问频率。从而提高数据源的处理能力。或者提高服务器的响应速度。
  • 一级缓存:基于 SqlSession 级别,默认开启,会话结束或执行更新操作(增删改)时失效。
  • 二级缓存:基于 namespace(Mapper 级别),需手动开启,跨会话共享,通过序列化机制实现。
  • 为什么会先走二级缓存再走一级缓存?
    • 二级缓存的作用域是SqlSessionFactory级别-90%找到。
    • 一级缓存是SqlSession级别的-5%找到。

MyBatis中如何实现缓存的扩展

  • 创建Cache接口的实现。重写getObjectputObject方法。
  • 怎么让我们自定义的实现:在cache标签中通过type属性关联我们自定义的Cache接口的实现。

如何实现延迟加载(懒加载)?

<association><collection> 中配置 fetchType="lazy",需全局启用 lazyLoadingEnabled=true

  • 全局懒加载
    <settings>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
    
  • 局部懒加载
    <resultMap id="userResultMap" type="User">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <collection property="orders" javaType="ArrayList" ofType="Order" select="selectOrdersByUserId" column="id" fetchType="lazy"/>
    </resultMap>
     
    <select id="selectUserById" resultMap="userResultMap">
        SELECT * FROM user WHERE id = #{id}
    </select>
     
    <select id="selectOrdersByUserId" resultType="Order">
        SELECT * FROM orders WHERE user_id = #{userId}
    </select>
    

MyBatis 插件(Plugin)原理?

基于动态代理,拦截 ExecutorStatementHandlerParameterHandlerResultSetHandler 的核心方法,实现自定义逻辑(如分页、性能监控)。

分页插件的实现原理?

拦截待执行 SQL,重写为分页查询(如 MySQL 的 LIMIT),并查询总数。

关联查询

一对一查询如何配置?

使用 <association> 标签,通过 property 指定对象属性,resultMapcolumn 映射关联结果。

<resultMap id="UserResultMap" type="User">
    <id property="id" column="id" />
    <result property="name" column="name" />
    <association property="address" javaType="Address">
        <id property="id" column="address_id" />
        <result property="city" column="city" />
        <result property="state" column="state" />
    </association>
</resultMap>
<select id="selectUserWithAddress" resultMap="UserResultMap">
    SELECT u.id, u.name, a.id as address_id, a.city, a.state
    FROM User u
    LEFT JOIN Address a ON u.address_id = a.id
</select>

一对多查询如何配置?

使用 <collection> 标签,类似一对一,但映射对象为集合类型。

<resultMap id="UserResultMap" type="User">
    <id property="id" column="id" />
    <result property="name" column="name" />
    <collection property="orders" ofType="Order">
        <id property="id" column="order_id" />
        <result property="orderDate" column="order_date" />
    </collection>
</resultMap>
<select id="selectUserWithOrders" resultMap="UserResultMap">
    SELECT u.id, u.name, o.id as order_id, o.order_date 
    FROM User u
    LEFT JOIN Order o ON u.id = o.user_id
</select>

嵌套查询 vs 嵌套结果的区别?

  • 嵌套查询:执行多次 SQL(可能引发 N+1 问题)。
  • 嵌套结果:单次复杂查询,通过 ResultMap 映射结果。

事务与性能

MyBatis 如何管理事务?

默认使用 JDBC 事务(通过 Connection 的提交/回滚),集成 Spring 后由 Spring 统一管理。

如何执行批量操作?

使用 SqlSessionBatchExecutor,或在动态 SQL 中使用 <foreach> 拼接批量语句。

常见问题排查

如何防止SQL注入

  • 优先使用 #{} 占位符

    SELECT * FROM users WHERE username = #{username}
    
  • 避免直接使用 ${} 拼接字符串

    SELECT * FROM users WHERE username = '${username}'
    
  • 安全使用动态 SQL 标签

    <select id="findUsers" parameterType="map">
      SELECT * FROM users
      <where>
        <if test="username != null">
          AND username = #{username}
        </if>
      </where>
    </select>
    
  • 强制校验 ${} 的使用场景

    • 必须使用时(如动态表名、排序字段):
      • 白名单过滤:仅允许预定义的合法值(如 orderBy 参数只接受 id, name)。
      • 避免用户输入直接控制:如从下拉菜单选择排序字段,而非自由输入。

Mapper 接口如何绑定到 XML?

通过 namespace 指定接口全限定名,方法名与 XML 中的 id 一致。
即:Java(包名+类名)=xml(namespace+id)

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

配置 useGeneratedKeys="true"keyProperty(如返回自增 ID 到对象的 id 属性)。

<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
  INSERT INTO user (name, email)
  VALUES (#{name}, #{email})
</insert>

遇到 BindingException 可能的原因?

Mapper 接口未扫描到、XML 中 id 与接口方法名不匹配、namespace配置错误。

扩展与集成

如何与 Spring 集成?

使用 mybatis-spring 库,配置 SqlSessionFactoryBeanMapperScannerConfigurer 扫描 Mapper 接口。

MyBatis 如何整合分布式缓存(如 Redis)?

自定义 Cache 接口实现类,替换默认的 PerpetualCache。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2319378.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Animation - AI Controller控制SKM_Manny的一些问题

一些学习笔记归档&#xff1b; 在UE5中&#xff0c;使用新的小白人骨骼&#xff1a;SKM_Manny&#xff0c;会跟UE4中的小白人有一些差别&#xff1b; 比如在用AI Controller控制使用该骨骼&#xff08;配置默认的ABP_Manny Animation BP&#xff09;角色的时候&#xff0c;需要…

安科瑞新能源防逆流解决方案:守护电网安全,赋能绿色能源利用

随着光伏、储能等新能源在用户侧的快速普及&#xff0c;如何避免电力逆流对电网造成冲击&#xff0c;成为行业关注的焦点。安科瑞凭借技术实力与丰富的产品矩阵&#xff0c;推出多场景新能源防逆流解决方案&#xff0c;以智能化手段助力用户实现安全、经济的能源管理&#xff0…

【一起学Rust | Tauri2.0框架】基于 Rust 与 Tauri 2.0 框架实现全局状态管理

前言 在现代应用程序开发中&#xff0c;状态管理是构建复杂且可维护应用的关键。随着应用程序规模的增长&#xff0c;组件之间共享和同步状态变得越来越具有挑战性。如果处理不当&#xff0c;状态管理可能会导致代码混乱、难以调试&#xff0c;并最终影响应用程序的性能和可扩…

扩散模型算法实战——三维重建的应用

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​ ​​​​​​ ​ ​ 1. 引言 三维重建是计算机视觉和图形学中的一个重要研究方向&#xff0c;旨在从二维图像或其他传感器数据中恢复…

社群经济4.0时代:开源链动模式与AI技术驱动的电商生态重构

摘要&#xff1a;在Web3.0技术浪潮与私域流量红利的双重驱动下&#xff0c;电商行业正经历从"流量收割"到"用户深耕"的范式转变。本文基于社群经济理论框架&#xff0c;结合"开源链动21模式"、AI智能名片、S2B2C商城小程序源码等创新工具&#x…

【Linux系统】进程等待:告别僵尸进程深入理解Linux进程同步的核心密码

Linux系列 文章目录 Linux系列前言一、进程等待的核心目的二、进程等待的实现方式2.1 wait()函数2.2 waitpid&#xff08;&#xff09;函数 总结 前言 在Linux系统中&#xff0c;进程等待&#xff08;Process Waiting&#xff09;是多进程编程中的核心机制&#xff0c;指父进程…

六十天前端强化训练之第二十五天之组件生命周期大师级详解(Vue3 Composition API 版)

欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗&#xff0c;谢谢大佬&#xff01; 目录 一、生命周期核心知识 1.1 生命周期全景图 1.2 生命周期钩子详解 1.2.1 初始化阶段 1.2.2 挂载阶段 1.2.3 更新阶段 1.2.4 卸载阶段 1.3 生命周期执行顺序 1.4 父子组…

springboot整合mybatis-plus(保姆教学) 及搭建项目

一、Spring整合MyBatis (1)将MyBatis的DataSource交给Spring IoC容器创建并管理&#xff0c;使用第三方数据库连接池(Druid&#xff0c;C3P0等)代替MyBatis内置的数据库连接池 (2)将MyBatis的SqlSessionFactory交给Spring IoC容器创建并管理&#xff0c;使用spring-mybatis整…

VSCode创建VUE项目(三)使用axios调用后台服务

1. 安装axios,执行命令 npm install axios 2. 在 main.ts 中引入并全局挂载 Axios 实例 修改后的 代码&#xff08;也可以单独建一个页面处理Axios相关信息等&#xff0c;然后全局进行挂载&#xff09; import { createApp } from vue import App from ./App.vue import rou…

车辆模型——运动学模型

文章目录 约束及系统移动机器人运动学模型&#xff08;Kinematic Model&#xff09;自行车模型含有加速度 a a a 的自行车模型系统偏差模型 在机器人的研究领域中&#xff0c;移动机器人的系统建模与分析是极为关键的基础环节&#xff0c;本文以非完整约束的轮式移动机器人为研…

【STM32实物】基于STM32的太阳能充电宝设计

基于STM32的太阳能充电宝设计 演示视频: 基于STM32的太阳能充电宝设计 硬件组成: 系统硬件包括主控 STM32F103C8T6、0.96 OLED 显示屏、蜂鸣器、电源自锁开关、温度传感器 DS18B20、继电器、5 V DC 升压模块 、TB4056、18650锂电池、9 V太阳能板、稳压降压 5 V三极管。 功能…

24-智慧旅游系统(协同过滤算法)

介绍 技术&#xff1a; 基于 B/S 架构 SpringBootMySQLLayuivue 环境&#xff1a; Idea mysql maven jdk1.8 管理端功能 管理端主要用于对系统内的各类旅游资源进行管理&#xff0c;包括用户信息、旅游路线、车票、景点、酒店、美食、论坛等内容。具体功能如下&#xff1a; …

Vue 中的日期格式化实践:从原生 Date 到可视化展示!!!

&#x1f4c5; Vue 中的日期格式化实践&#xff1a;从原生 Date 到可视化展示 &#x1f680; 在数据可视化场景中&#xff0c;日期时间的格式化显示是一个高频需求。本文将以一个邀请码关系树组件为例&#xff0c;深入解析 Vue 中日期格式化的 核心方法、性能优化 和 最佳实践…

2025年使用Scrapy和Playwright解决网页抓取挑战的方案

0. 引言 随着互联网技术的发展&#xff0c;网页内容呈现方式越来越复杂&#xff0c;大量网站使用JavaScript动态渲染内容&#xff0c;这给传统的网络爬虫带来了巨大挑战。在2025年的网络爬虫领域&#xff0c;Scrapy和Playwright的结合为我们提供了一个强大的解决方案&#xff…

可靠消息投递demo

以下是一个基于 Spring Boot RocketMQ 的完整分布式事务实战 Demo&#xff0c;包含事务消息、本地事务、自动重试、死信队列&#xff08;DLQ&#xff09; 等核心机制。代码已充分注释&#xff0c;可直接运行。 一、项目结构 src/main/java ├── com.example.rocketmq │ …

Copilot提示词库用法:调整自己想要的,记住常用的,分享该共用的

不论你是 Microsoft 365 Copilot 的新用户还是熟练运用的老鸟&#xff0c;不论你是使用copilot chat&#xff0c;还是在office365中使用copilot&#xff0c;copilot提示词库都将帮助你充分使用copilot这一划时代的产品。它不仅可以帮助你记住日常工作中常用的prompt提示词&…

Python实战(3)-数据库操作

前面说过&#xff0c;可用的SQL数据库引擎有很多&#xff0c;它们都有相应的Python模块。这些数据库引擎大都作为服务器程序运行&#xff0c;连安装都需要有管理员权限。为降低Python DB API的使用门槛&#xff0c;我选择了一个名为SQLite的小型数据库引擎。它不需要作为独立的…

LeetCode 160 Intersection Of Two Linked Lists 相交链表 Java

题目&#xff1a;找到两个相交列表的起始点&#xff0c;如图c1开始为A和B两个链表的相交点 举例1&#xff1a;8为两个链表的相交点。 注意&#xff1a;相交不止是数值上的相同。 举例2&#xff1a;2为相交点 举例3&#xff1a;没有相交点 解题思路&#xff1a; 相交证明最后一…

AI Agent中的MCP详解

一、协议定义与核心价值 MCP(Model Context Protocol,模型上下文协议)是由Anthropic公司于2024年11月推出的开放标准协议,其核心目标是通过建立统一接口规范,解决AI模型与外部系统集成效率低下的行业痛点。该协议通过标准化通信机制,使大型语言模型(LLM)能够无缝对接数…

win系统上自动化安装配置WSL linux和各种生信工具教程

windows系统上自动化安装配置WSL linux系统和各种生信工具教程 高通量测序原始数据的上游分析模块介绍 我开发的OmicsTools软件的这些分析测序原始数据的上游处理分析模块需要使用到linux和linux系统中的一些生信工具&#xff0c;在这里我开发了在windows系统中自动化安装WSL …