mybatis面试

1.说一下对Mybatis的理解

1.1 mybatis概念

mybatis是一个半自动的持久层ORM框架

1.2 什么是ORM

Object Relational Mapping【对象 关系 映射】,将Java中的对象与数据库中建议映射关系

1.3 Mybatis与Hibernate对比

Mybatis是一个半自动化,需要手写SQL;Hibernate是全自动化,无需手写SQL

1.4 Mybatis与JDBC对比

Mybatis是在JDBC基础之上封装的;JDBC是Java提供的能够直接使用Java代码来编写SQL语句并执行数据库操作的标准API,JDBC需要开发人员在Java代码中编写sql,耦合度高,mybatis可以通过xml方式和Java代码解耦

2. Mybatis的xml映射文件的规则

  1. xml映射文件的位置:resources/mapper文件夹下
  2. 映射文件名称要和Java接口名称一致
  3. 映射文件的namespace与接口的全限定名一致
  4. 映射文件的标签id和接口方法名称一致

3. 自定义映射

3.1 resultMap和resultType区别

  1. resultMap和resultType都是用来映射查询结果集的,当数据库字段属性名和Java对应的实体相同时可以直接使用resultType
  2. 如果当数据库字段属性名和Java对应的实体不相同,例如实体中字段是userName,数据库是user_name,那么就查询出的结果集就和Java实体对应不上,有两种解决办法
  • 起别名 例如 user_name as userName
    <select id="selectUser" resultType="User">select id,user_name as userName from user where id = #{id}</select>
  • 使用resultMap配置映射关系
    <resultMap id="userMap" type="com.lby.dto.User"><id column="id" jdbcType="INTEGER" property="id" /><result column="user_name" jdbcType="VARCHAR" property="userName" /></resultMap><select id="selectUser" resultMap="userMap">select id,user_name from user where id = #{id}</select>
  1. resultMap和resultType只能使用一个

3.2 association和collection 映射

    <resultMap id="userAndDeptResultMapAssociation" type="employee"><!--  定义主键字段与属性关联关系 --><id column="id" property="id"></id><!--  定义非主键字段与属性关联关系--><result column="user_name" property="userName"></result><!--  用戶所属部门,自定义关联关系--><association property="dept" javaType="com.lby.mybatis.pojo.Dept"><id column="dept_id" property="deptId"></id><result column="dept_name" property="deptName"></result></association></resultMap><resultMap id="userAndEmpResultMap" type="dept"><id property="deptId" column="dept_id"></id><result property="deptName" column="dept_name"></result><collection property="empList" ofType="com.lby.mybatis.pojo.Employee"><id column="id" property="id"></id><result column="last_name" property="lastName"></result><result column="email" property="email"></result><result column="salary" property="salary"></result></collection></resultMap>
  • association标签:定义一对一或多对一关联关系
    • colunm:设置SQL中参数
    • property:SQL关联实体的属性
    • javaType:关联实体属性的类型
    • select:设置分步查询SQL全路径
    • fetchType:设置局部延迟加载【懒加载】是否开启
  • collection标签:定义一对多的关联关系
    • property:SQL关联实体的属性
    • ofType:关联实体属性的类型
    • fetchType:设置局部延迟加载【懒加载】是否开启

4. Mybatis插入数据的时候,怎样获取插入数据后的主键id

  • useGeneratedKeys:启用主键生成策略,添加成功后可以返回主键值,并存储到keyProperty
  • keyProperty:设置存储属性值,对应的是Java实体中的属性
    <insert id="addUser" useGeneratedKeys="true" keyProperty="id" parameterType="User">insert into user (id,user_name) values (#{id},#{userName})</insert>

5. mybatis中的参数是如何传递的

5.1 自定义个数参数

@Param可以将接口的参数和xml中#{}的参数进行映射

public List<Employee> selectEmpByNamed(@Param("lName")String lastName, @Param("salary") double salary);

5.2 复杂类型类类型Bean传参

    Integer updateByPrimaryKey(UserDTO dto);
    <update id="updateByPrimaryKey" parameterType="UserDTO" >update user<set ><if test="userName != null" >user_name = #{userName,jdbcType=VARCHAR},</if></set>where id = #{id,jdbcType=BIGINT}</update>

5.3 map参数

    <select id="queryUserList" resultMap="UserMap" parameterType="java.util.Map">select<include refid="Base_Column_List" />from user uwhere 1=1<if test="userName != null">and  u.user_name = #{userName,jdbcType=VARCHAR}</if>ORDER BY u.id</select>

5.4集合参数传递

public List<User> selectUserList(@Param("ids") List<Integer> ids);
    <select id="selectUserByIds" resultType="User">SELECT `id`, user_name FROM `tbl_employee`<where>`id` in (<foreach collection="ids" item="id" separator=",">#{id}</foreach>)</where></select>

6. 参数传递#和$区别

  1. 【#】底层执行SQL语句的对象,使用PreparedStatementd,预编译SQL,防止SQL注入安全隐患,相对比较安全。
  2. 【$】底层执行SQL语句的对象使用Statement对象,未解决SQL注入安全隐患,相对不安全。

7. mybatis查询返回值的集中情况

7.1 返回单个对象

	public User selectUserById(int id);
    <select id="selectUserById" resultType="user">SELECT id, user_name as userName FROM user WHERE id= #{id}</select>

7.2 返回对象集合

	public List<User> selectAllUser();
    <select id="selectAllUser" resultType="user">SELECT id, user_name as userName FROM user</select>

如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。

7.3 返回Map集合

  • 对象的id作为key
  • 对象作为value
	@MapKey("id")public Map<Integer,User> selectUserReturnMap();
    <select id="selectUserReturnMap" resultType="map">SELECT id, user_name as userName FROM user</select>

8. mybatis的分步查询

  1. 为什么要分步查询?
    多表关联查询时,可能会导致性能低下,通过分步查询,可以减少表连接的次数
  2. 如何进行分布查询?
    在一对多的association情况下,可以借助select属性,引用查询,具体实现如下
  • java代码
@Data
public class User {private int id;private String username;private List<Order> orders;
}
@Data
public class Order {private int id;private int userId;private String product;
}
  • Mapper接口
import java.util.List;
public interface UserMapper {User getUserById(int userId);
}
  • XML映射文件
<!-- UserMapper.xml -->
<mapper namespace="com.example.mapper.UserMapper"><resultMap id="userResultMap" type="User"><id property="id" column="id"/><result property="username" column="username"/><!-- 使用association的select属性实现分步查询 --><association property="orders" javaType="List" select="getOrdersByUserId"/></resultMap><select id="getUserById" resultMap="userResultMap" parameterType="int">SELECT * FROM users WHERE id = #{userId}</select><select id="getOrdersByUserId" resultMap="orderResultMap" parameterType="int">SELECT * FROM orders WHERE user_id = #{userId}</select></mapper>

9. Mybatis延迟加载

  1. 什么是延迟加载
    需要时加载,不需要不加载
  2. 有什么好处
    只在必要的时候才查询,提高性能
  3. 如何实现延迟加载
  • 全局配置
<!-- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 设置加载的数据是按需加载3.4.2及以后的版本该步骤可省略-->
<setting name="aggressiveLazyLoading" value="false"/>
  • 局部配置
    使用fetchType属性:
    eager:关闭局部延迟加载
    lazy:开启局部延迟加载
<association property="dept"select="com.atguigu.mybatis.mapper.DeptMapper.selectDeptByDeptId"column="dept_id"fetchType="eager">
</association>

10. 动态sql

  • if标签:用于完成简单的判断
  • where标签:用于解决where关键字及where后第一个and或or的问题
  • trim标签: 可以在条件判断完的SQL语句前后添加或者去掉指定的字符
    • prefix: 添加前缀
    • prefixOverrides: 去掉前缀
    • suffix: 添加后缀
    • suffixOverrides: 去掉后缀
  • set标签:主要用于解决set关键字及多出一个【,】问题
  • choose标签:类似java中if-else【switch-case】结构
  • foreach标签:类似java中for循环
    • collection: 要迭代的集合
    • item: 当前从集合中迭代出的元素
    • separator: 元素与元素之间的分隔符
    • open: 开始字符
    • close:结束字符
  • sql标签:提取可重用SQL片段
    <sql id="emp_col">id,last_name,email,salary</sql><sql id="select_employee">selectid,last_name,email,salaryfromtbl_employee</sql><!-- 按条件查询员工信息【条件不确定】--><select id="selectEmpByOpr" resultType="employee"><include refid="select_employee"></include><where><if test="id != null">and id = #{id}</if><if test="lastName != null">and last_name = #{lastName}</if><if test="email != null">and email = #{email}</if><if test="salary != null">and salary = #{salary}</if></where></select><select id="selectEmpByOprTrim" resultType="employee"><include refid="select_employee"></include><trim prefix="where" suffixOverrides="and"><if test="id != null">id = #{id} and</if><if test="lastName != null">last_name = #{lastName} and</if><if test="email != null">email = #{email} and</if><if test="salary != null">salary = #{salary}</if></trim></select><update id="updateEmpByOpr">updatetbl_employee<set><if test="lastName != null">last_name=#{lastName},</if><if test="email != null">email=#{email},</if><if test="salary != null">salary=#{salary}</if></set>whereid = #{id}</update><select id="selectEmpByOneOpr" resultType="employee">select<include refid="emp_col"></include>fromtbl_employee<where><choose><when test="id != null">id = #{id}</when><when test="lastName != null">last_name = #{lastName}</when><when test="email != null">email = #{email}</when><when test="salary != null">salary = #{salary}</when><otherwise>1=1</otherwise></choose></where></select><select id="selectEmpByIds" resultType="employee">selectid,last_name,email,salaryfromtbl_employee<where>id in(<foreach collection="ids" item="id" separator=",">#{id}</foreach>)</where></select><insert id="batchInsertEmp">INSERT INTOtbl_employee(last_name,email,salary)VALUES<foreach collection="employees" item="emp" separator=",">(#{emp.lastName},#{emp.email},#{emp.salary})</foreach></insert>

11. mybatis缓存机制

mybaits有二级缓存

11.1 一级缓存

  1. 基本概念
    一级缓存的模式有两种,默认是sqlSession级别对当前回话有效,另一种是statement是sql级别,sqlSession级别缓存在分布式环境下,一个sqlSession更新了数据,其他缓存结果的sqlSession是看不到更新后数据的,所以建议将缓存级别设定为Statetment
  2. sqlSession缓存的原理
    第一次获取数据,先从数据库加载数据,将数据缓存到Mybatis一级缓存中,一级缓存使用的是map,其中key是 hashCode + 查询sql的id + 编写sql的查询语句 + 参数构成;再次获取数据时,先从一级缓存获取,未获取到再成数据库中获取
  3. 一级缓存的失效情况
  • sql相同,但是sqlSession不同
  • 相同sqlSession中,两次相同sql查询中间执行了任何的增删改操作(这个操作会导致清空缓存)
  • 相同sqlSession中的两次相同搞的sql查询中间提交了事务

11.2 二级缓存

  1. 概念
    二级缓存是SqlSessionFactory级别的缓存,二级缓存默认关闭,二级缓存需要提交sqlSession或者关闭sqlSession才会缓存。
  2. 二级缓存如何使用
  • 全局配置文件开启二级缓存
<setting name="cacheEnabled" value="true"/>
  • 开始二级缓存对应的实体PO需要实现Serializable接口
  • 在对应需要序列化的xml映射文件标签中使用
  1. 二级缓存原理
    第一次查询先从数据库获取数据,让后将书记缓存到一级缓存,当SqlSession提交或者关闭后,将数据缓存到二级缓存;再次获取数据时先从一级缓存获取,一级缓存没有数据再从二级缓存获取,二级缓存也没有从数据库获取
  2. 二级缓存失效情况
    两次查询中见,执行增删改操作,一级二级缓存都会被清空

12. Mybatis字段映射原理

  1. 通过JDBC API向数据库发送SQL查询语句,获取查询结果集
  2. 结果集每一行的数据都封装成ResultSet对象
  3. 每一行数据,mybatis都会根据Java对象的属性和结果集的列名称匹配,匹配成功,则将结果映射到对应属性中
  4. 对于实体属性和对应表的列不一致,可以在sql中使用AS,或者通过resultMap定义映射关系
  5. 最终mybatis会将所有的映射成功的Java对象封装成一个List集合返回

13. 获取SqlSession的流程是怎样的

  1. SqlSessionFactoryBuilder解析配置文件,生成一个Configration对象,这个对象中包含了MyBatis需要的所有配置,然后会用这个Configration对象创建一个SqlSessionFactory对象,这个对象中包含了Configration对象。
  2. 调用SqlSessionFactory的openSesison方法,这个方法会创建一个Sql执行器(Executor组件中包含了Transaction对象),这个Sql执行器会代理你配置的拦截器方法。
  3. 获得上面的Sql执行器后,会创建一个SqlSession(默认使用DefaultSqlSession),这个SqlSession中也包含了Configration对象和上面创建的Executor对象,所以通过SqlSession也能拿到全局配置;获得SqlSession对象后就能执行各种CRUD方法了。

14. mysql的Sql是怎样执行的

  1. 调用SqlSession的getMapper方法,获得Mapper接口的动态代理对象MapperProxy
  2. 调用Mapper接口的所有方法都会调用MapperProxy的invoke方法(动态代理机制)创建MapperMethod对象
  3. 调用MapperMethod的execute方法,sqlSession会作为execute方法的入参
  4. 进入Executor组件的query方法,这个方法中会创建一个StatementHandler对象,这个对象中同时会封装ParameterHandler和ResultSetHandler对象。
  5. 使用ParameterHandler来给sql设置参数。
  6. 使用StatementHandler的增删改查方法获得结果,ResultSetHandler对结果进行封装转换,请求结束。

Executor、StatementHandler 、ParameterHandler、ResultSetHandler,Mybatis的插件会对上面的四个组件进行动态代理。

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

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

相关文章

Java多线程文档与入门-Thread与Runnable

一.Thread Fields Modifier and TypeField and Descriptionstatic intMAX_PRIORITY 线程可以拥有的最大优先级。 static intMIN_PRIORITY 线程可以拥有的最小优先级。 static intNORM_PRIORITY 分配给线程的默认优先级。 构造方法 Constructor and DescriptionThread() 分配一…

每日一道Java面试题:说一说Java中的异常

写在开头 任何一个程序都无法保证100%的正常运行&#xff0c;程序发生故障的场景&#xff0c;我们称之为&#xff1a;异常&#xff0c;在Java中对于异常的处理有一套完善的体系&#xff0c;今天我们就来一起学习一下。老样子&#xff0c;用一段简单的代码开始今天的学习。 我&a…

【CanvasKeyFrames - HTML5 Canvas 图片序列帧播放工具】

前言 一、CanvasKeyFrames 是什么&#xff1f; 用来做canvas动画的工具。 二、使用步骤 效果如图&#xff1a;上下波动的线条 1.引入库 代码如下&#xff08;示例&#xff09;&#xff1a; 在html中引入&#xff1a; <script src"canvas-keyframes.js"><…

中国34省市区名字之来源

本文内容是笔者根据B站视频进行整理,视频内容由@顺丰快递曹子桓 @小玄学投稿。 北京 洪武二年,朱元璋得知捷报,改“大都路”为“北平府”,取“蓟北悉平”之意。 朱棣改北平府为顺天府,又赐京号——北京。 民国时,顺天府先被改为京兆地方,又被改为北平市。 新中国成立后…

源聚达科技:开一家抖音小店有没有风险

在数字化浪潮的推动下&#xff0c;抖音小店如雨后春笋般涌现&#xff0c;成为众多创业者眼中的香饽饽。然而&#xff0c;“盛名之下&#xff0c;其实难副”&#xff0c;开设一家抖音小店并非只有风光无限&#xff0c;其背后的风险也不容小觑。 首要的风险源自激烈的市场竞争。抖…

力扣之2629.复合函数(reduceRight )

/*** param {Function[]} functions* return {Function}*/ var compose function(functions) {return function(x) {return functions.reduceRight((result, func) > func(result), x);} };/*** const fn compose([x > x 1, x > 2 * x])* fn(4) // 9*/ 说明&#x…

大模型ReAct智能体开发实战

哆啦A梦是很多人都熟悉的角色&#xff0c;包括我自己。 在成长过程中&#xff0c;我常常对他口袋里的许多小玩意感到惊讶&#xff0c;而且他知道何时使用它们。 随着大型语言模型 (LLM) 的发展趋势&#xff0c;你也可以构建一个具有相同行为方式的模型&#xff01; 我们将构建…

Redis是单线程还是多线程?

Redis最初是设计为单线程的服务器&#xff0c;其核心处理命令请求的逻辑是单线程的&#xff0c;这使得Redis非常简单而高效。核心单线程的设计意味着它使用非阻塞I/O&#xff0c;并且按顺序处理所有操作&#xff0c;从而避免了锁和多线程的竞争条件。 然而&#xff0c;在最近的…

DHCP简介

定义 动态主机配置协议DHCP&#xff08;Dynamic Host Configuration Protocol&#xff09;是一种用于集中对用户IP地址进行动态管理和配置的技术。即使规模较小的网络&#xff0c;通过DHCP也可以使后续增加网络设备变得简单快捷。 DHCP是在BOOTP&#xff08;BOOTstrap Protoc…

组装2-4人后端服务团队,选择GO还是Java?

问题&#xff1a; 组装2-4人后端服务团队&#xff0c;选择GO还是Java&#xff1f; 背景&#xff1a; 原团队python背景&#xff0c;现新业务需要用到大数据的处理&#xff0c;而python并不适合。 原业务的发展本想渐进发展中部分大数据业务改用GO实现逻辑部分&#xff0c;但新…

mysql数据库学习记录(一)

文章目录 1.mysql如何加外键关联约束&#xff1f;2.mysql&#xff0c;加外键关联约束有什么作用&#xff1f;3.在MySQL中&#xff0c;可以通过在创建数据表时使用PRIMARY KEY关键字来指定多列联合主键&#xff0c;那么请问联合主键有啥作用&#xff1f;mysql数据表设计好后&…

linux 04 进程管理

02.进程管理 ps 在命令行输入ps后按回车键就能查看当前系统中正在运行的进程。 第一. 查看进程ps 进程的状态STAT 进程的周期 fork&#xff0c;产生一个新进程 第二.排序进程表 ps aux --sort -%cpu 降序cpu %cpu 增序cpu 第三.父子关系 ps ef 第四.自定义 五.动态查看…

Spring和SpringBoot的区别是什么

Spring 和 Spring Boot 是 Java 开发领域内两个极其重要且紧密相关的框架&#xff0c;它们各自在企业级应用开发中扮演着不同的角色&#xff0c;并带来了一系列革新性的变化。以下是关于两者之间主要区别的详细分析&#xff1a; 一、设计理念与定位 Spring Framework Spring 是…

如何远程登录云服务器?登录失败是什么原因?

我用Linux云服务器&#xff0c;遇到了有关远程登录的一些问题&#xff0c;于是搜索了一些资料&#xff0c;整理了一篇文档&#xff0c;作为记录。如果你也遇到过 相似的问题&#xff0c;欢迎一起探讨&#xff01; 一、Linux云服务器的远程登录 远程登陆linux&#xff0c;使用…

【Java 数据结构】排序

排序算法 1. 排序的概念及引用1.1 排序的概念1.2 常见的排序算法 2. 常见排序算法的实现2.1 插入排序2.1.1 直接插入排序2.1.2 希尔排序( 缩小增量排序 ) 2.2 选择排序2.2.1 直接选择排序2.2.2 堆排序 2.3 交换排序2.3.1冒泡排序2.3.2 快速排序2.3.3 快速排序非递归 2.4 归并排…

Pinterest是什么软件?有什么功能?Pinterest怎么做营销?

如今&#xff0c;社媒营销已成为连接品牌与全球消费者的关键桥梁。随着像Instagram、Twitter等海外社交媒体平台的兴起&#xff0c;社媒营销人员和跨境电商面临着无限的机遇。而在这些平台中&#xff0c;有一个平台以其独特的视觉展示方式和高度专注的用户体验脱颖而出——那就…

力扣hot100 无重复字符的最长子串 双指针 滑动窗口 哈希

Problem: 3. 无重复字符的最长子串 文章目录 思路Code 思路 &#x1f468;‍&#x1f3eb; 参考 Code ⏰ 时间复杂度: O ( n ) O(n) O(n) &#x1f30e; 空间复杂度: O ( 1 ) O(1) O(1) class Solution {public int lengthOfLongestSubstring(String s){if (s null ||…

HTML+CSS+JS的3D进度条

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>HTMLCSSJS的3D进度条</title><style>…

ios app与H5页面交互踩坑

ios 与 H5 页面交互是异步的&#xff0c;有坑 这两端的交互我这边写的如下&#xff1a; const platform 判断的平台 export const getIosData () > {let returnPromise;try {if (platform "android" ) {returnPromise Promise.resolve((window as any).androi…

【JAVA学习路线——超详细介绍】

JAVA学习路线——超详细介绍 1. 介绍2. Java基础知识3. Java进阶4. Java高级知识5. 开发工具和环境6. 涉猎相关技术7. 实战项目8. 持续学习和实践 1. 介绍 要成为一名熟练的Java开发者&#xff0c;需要经过系统的学习和实践&#xff0c;下面是一个详细的Java学习路线&#xff…