Java最全面试总结——5. MyBatis篇

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很好的集成;

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

缺点

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

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

3、#{}和${}的区别是什么?

#{}是预编译处理,${}是字符串替换。

Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值; Mybatis在处理${}时,就是把${}替换成变量的值。

使用#{}可以有效的防止SQL注入,提高系统安全性。

4、当实体类中的属性名和表中的字段名不一样 ,怎么办 ?

第1种: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。

<select id=”selectorder” parametertype=”int” resultetype=”me.gacl.domain.order”>select order_id id, order_no orderno ,order_price price form orders where
order_id=#{id}; </select> 

 第2种: 通过来映射字段名和实体类属性名的一一对应的关系。

 <select id="getOrder" parameterType="int" resultMap="orderresultmap">select * from orders where order_id=#{id} </select> <resultMap type=”me.gacl.domain.order” id=”orderresultmap”> <!–用id属性来映射主键字段–> <id property=”id” column=”order_id”> <!–用result属性来映射非主键字段,property为实体类属性名,column为数据表中的属性–> <result property = “orderno” column =”order_no”/> <result property=”price” column=”order_price” /> </reslutMap> 

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

Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分 页。可以在sql内直接拼写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页,比如:MySQL数据的时候,在原有SQL后面拼写limit。 分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截 待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

6、Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?

第一种是使用标签,逐一定义数据库列名和对象属性名之间的映射关系。

第二种是使用sql列的别名功能,将列的别名书写为对象属性名。 有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋 值并返回,那些找不到映射关系的属性,是无法完成赋值的。

7、 如何执行批量插入?

首先,创建一个简单的insert语句:

 <insert id=”insertname”> insert into names (name) values (#{value}) </insert> 

然后在java代码中像下面这样执行批处理插入:

 list<string> names = new arraylist(); names.add(“fred”); names.add(“barney”); names.add(“betty”); names.add(“wilma”); // 注意这里 executortype.batch sqlsession sqlsession = sqlsessionfactory.opensession(executortype.batch);try { namemapper mapper = sqlsession.getmapper(namemapper.class);for (string name : names) { mapper.insertname(name); } sqlsession.commit(); }catch(Exception e){ e.printStackTrace(); sqlSession.rollback(); throw e; } finally { sqlsession.close(); } 

8、Xml映射文件中,除了常见的select|insert|updae|delete 标签之外,还有哪些标签?

加上动态sql的9个标签,其中为sql片段标签,通过标签引入sql片段,为不支持自增的主键生成策 略标签。

9、MyBatis实现一对一有几种方式?具体怎么操作的?

有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置 association节点配置一对一的类就可以完成;

嵌套查询是先查一个表,根据这个表里面的结果的 外键id,去再另外一个表里面查询数据,也是通过 association配置,但另外一个表的查询通过select属性配置。

10、Mybatis是否支持延迟加载?如果支持,它的实现原理是什么

Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一 对一,collection指的就是一对多查询。

在Mybatis配置文件中,可以配置是否启用延迟加载 lazyLoadingEnabled=true|false。 它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的 查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。

当然了,不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。

11、说说Mybatis的缓存机制:

Mybatis整体:

 一级缓存localCache

在应用运行过程中,我们有可能在一次数据库会话中,执行多次查询条件完全相同的 SQL, MyBatis 提供了一级缓存的方案优化这部分场景,如果是相同的 SQL 语句,会优先命中一级缓存, 避免直接对数据库进行查询,提高性能。

每个 SqlSession 中持有了 Executor,每个 Executor 中有一个 LocalCache。当用户发起查询时, MyBatis 根据当前执行的语句生成 MappedStatement,在 Local Cache 进行查询,如果缓存命中 的话,直接返回结果给用户,如果缓存没有命中的话,查询数据库,结果写入 Local Cache,最后 返回结果给用户。具体实现类的类关系图如下图所示:

1. MyBatis 一级缓存的生命周期和 SqlSession 一致。

2. MyBatis 一级缓存内部设计简单,只是一个没有容量限定的 HashMap,在缓存的功能性上有 所欠缺。

3. MyBatis 的一级缓存最大范围是 SqlSession 内部,有多个 SqlSession 或者分布式的环境下, 数据库写操作会引起脏数据,建议设定缓存级别为 Statement。

二级缓存

在上文中提到的一级缓存中,其最大的共享范围就是一个 SqlSession 内部,如果多个 SqlSession 之间需要共享缓存,则需要使用到二级缓存。开启二级缓存后,会使用 CachingExecutor 装饰 Executor,进入一级缓存的查询流程前,先在 CachingExecutor 进行二级缓存的查询,具体的工作 流程如下所示。 

二级缓存开启后,同一个 namespace 下的所有操作语句,都影响着同一个 Cache,即二级缓存被 多个 SqlSession 共享,是一个全局的变量。

当开启缓存后,数据的查询执行的流程为: 

二级缓存 -> 一级缓存 -> 数据库

1. MyBatis 的二级缓存相对于一级缓存来说,实现了 SqlSession 之间缓存数据的共享,同时粒度 更加细,能够到 namespace 级别,通过 Cache 接口实现类不同的组合,对Cache的可控性也更强。

2. MyBatis 在多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用二级缓存的条件 比较苛刻。

3. 在分布式环境下,由于默认的 MyBatis Cache 实现都是基于本地的,分布式环境下必然会出现 读取到脏数据,需要使用集中式缓存将 MyBatis 的 Cache 接口实现,有一定的开发成本,直 接使用 Redis、Memcached 等分布式缓存可能成本更低,安全性也更高。

12、JDBC 编程有哪些步骤?

1.装载相应的数据库的 JDBC 驱动并进行初始化:

Class.forName("com.mysql.jdbc.Driver"); 

2.建立 JDBC 和数据库之间的 Connection 连接:

Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?
characterEncoding=UTF-8", "root", "123456");

3.创建 Statement 或者 PreparedStatement 接口,执行 SQL 语句。

4.处理和显示结果。

5.释放资源。

13、MyBatis 中见过什么设计模式?

 14、MyBatis 中比如 UserMapper.java 是接口,为什么没有实现类还能调用?

使用JDK动态代理+MapperProxy。本质上调用的是MapperProxy的invoke方法。

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

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

相关文章

四个ChatGPT在学术论文写作中的要点!【建议收藏】

在论文写作过程中&#xff0c;写作不仅是一种表达&#xff0c;更是一种艺术。论文写作是一项复杂而精细的任务&#xff0c;它要求作者不仅能清晰地传达思想&#xff0c;还要能够精确地界定研究范围和问题。这是一个充满挑战的过程&#xff0c;特别是当你试图将那些盘旋在脑海中…

深度解析Sora的核心技术

Sora要解决的核心问题 Sora面临的挑战是将不同类型的视觉信息&#xff0c;如视频、文本、图像和声音等&#xff0c;整合为一种共同的表征形式。这种转换是实现统一训练过程的关键&#xff0c;旨在将各类数据集中到一个训练框架中&#xff0c;以便于进行大规模的统一学习。简而…

http 和 https 的区别?

目录 1.http 和 https 的基本概念 2.http 和 https 的区别 3.https 协议的工作原理 4.https 协议的优点 5.https 协议的缺点 1.http 和 https 的基本概念 http: 超文本传输协议&#xff0c;是互联网上应用最为广泛的一种网络协议&#xff0c;是一个客户端和服务器端请求和…

穿越时空的命令行:TELNET的历史、原理与未来展望

引言 TELNET&#xff0c;代表"远程终端协议"&#xff0c;是一种允许用户通过互联网或局域网在本地计算机上登录并操作远程计算机的协议。它提供了一种简单的方式来访问远程服务器&#xff0c;执行命令并管理资源&#xff0c;是早期互联网重要的通信协议之一。 TELN…

lodash库中的函数处理嵌套的对象和数组的函数

import { isArray, camelCase, isObject, snakeCase, transform } from lodash-es;const toSnakeCase obj > transform(obj, (acc, value, key, target) > {const camelKey isArray(target) ? key : snakeCase(key);acc[camelKey] isObject(value) ? toSnakeCase(va…

rime 输入²⁰²⁴/₀₂.₂₁ 格式日期

如何书写一个日期,例如 2024/02/21 星期三、Feb. 21th, 2024、20240221、甲辰(龙)年正月十二,现在我们介绍一种新的日期格式 ⁰⁴/₀₂.₂₁ 的输入方法。 上标字符 在rime输入法中,我们可以使用符号/来启动特殊符号的输入,例如我们可以通过/sb来输入上标字符,如下👇:…

WebRTC最新版报错解决:city.wav:missing and no known rule to make it (二十六)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

CheatEngine基础进阶篇

我们在上一篇文章里说了CE的安装,汉化以及最基础最基础的值扫描和修改方法,当然很多游戏不能通过这些简单的手段就能达到修改值的效果,因此我们还需要掌握以下几个重要的知识点: 指针寻址 上一步阐述了如何使用"代码查找"功能对付变化位置的数据地址,但这种方法…

鸿蒙应用开发,比 React 体验更好

痛点 一直以来&#xff0c;使用 HTML CSS 来表达 UI 结构&#xff0c;都有一个若隐若现的痛点。痛点来源主要体现在 DOM 结构的语义表现力不足。 例如这样一段代码&#xff0c;我们能够很清晰的知道 DOM 结构是怎么样的&#xff0c;但是其具体的布局结构方式和特性就不知道了…

vue.config.js中proxy配置

这里以axios发请求为例 axios.get("/abc/def"); axios.get("/abc/ghi"); axios.post("/abc/jkm"); //axios发送的请求是本地的服务器地址拼接上发送的请求&#xff0c;如 http://localhost:8080/abc/def如果发送的请求都以 /abc 开头&#xff0…

Redis面试题关于持久化的问题

什么是Redis持久化&#xff1f;Redis有哪几种持久化方式&#xff1f;优缺点是什么&#xff1f; 持久化就是把内存的数据写到磁盘中去&#xff0c;防止服务宕机了内存数据丢失。 Redis 提供了两种持久化方式:RDB&#xff08;默认&#xff09; 和AOF RDB&#xff1a; rdb是Red…

考什么呢?

年后的第一天复工&#xff1a; 请了一天假&#xff0c;迟回来一天&#xff0c;等到中午吃饭的时候&#xff0c;有些恍惚&#xff0c;感觉身边的人自从上班之后&#xff0c;每天过的麻木的生活&#xff0c;到饭点了&#xff0c;就去吃饭&#xff0c;生活没有一丝激情&#xff0c…

C语言获取时间函数大全

一、最简单获取秒数的&#xff0c;windows和linux逗支持用time()函数,获取从1970年到现在过了多少秒&#xff0c;time_t其实是long int 类型 time_t starttime(NULL); for(long i0;i<10000000000;) i1; time_t endtime(NULL) printf("经过了%d秒",end-start); 二…

五种多目标优化算法(MOJS、MOGWO、NSWOA、MOPSO、NSGA2)性能对比,包含6种评价指标,9个测试函数(提供MATLAB代码)

一、5种多目标优化算法简介 1.1MOJS 1.2MOGWO 1.3NSWOA 1.4MOPSO 1.5NSGA2 二、5种多目标优化算法性能对比 为了测试5种算法的性能将其求解9个多目标测试函数&#xff08;zdt1、zdt2 、zdt3、 zdt4、 zdt6 、Schaffer、 Kursawe 、Viennet2、 Viennet3&#xff09;&#xff0…

域名 SSL 证书信息解析 API 数据接口

域名 SSL 证书信息解析 API 数据接口 网络工具&#xff0c;提供域名 SSL 证书信息解析&#xff0c;多信息查询&#xff0c;毫秒级响应。 1. 产品功能 提供域名 SSL 证书信息解析&#xff1b;最完整 SSL 属性信息解析&#xff1b;支持多种元素信息抽取&#xff0c;包括主题的可…

Sample Pairing(ICLR 2018)

paper&#xff1a;Data Augmentation by Pairing Samples for Images Classification 本文的创新点 本文提出了一种新的应用于图像分类的数据增强方法SamplePairing&#xff0c;这种简单的数据增强技术显著提高了所有测试的数据集的分类精度。此外当训练集中的样本数量非常少…

Web前端3D JS框架和库 整理

在WebGL库和SVG/Canvas元素的支持下&#xff0c;JavaScript变得惊人的强大。几乎可以为网络构建任何东西&#xff0c;包括基于浏览器的游戏和本地应用&#xff0c;许多最新的突破性功能都在3D上运行。 为此&#xff0c;「数维图小编」整理了19个交互式3D Javascript库和框架&am…

NestJS入门6:日志中间件

前文参考&#xff1a; NestJS入门1 NestJS入门2&#xff1a;创建模块 NestJS入门3&#xff1a;不同请求方式前后端写法 NestJS入门4&#xff1a;MySQL typeorm 增删改查 NestJS入门5&#xff1a;加入Swagger 1. 安装 nest g middleware logger middleware​ ​ ​ 2. lo…

关于发送邮件时Reply Reply All和Forward的区别

我们发送邮件的时候总是会纠结到底是用回复&#xff0c;还是回复全部&#xff0c;还是转发。 回复- 仅回复发件人。 全部回复- 回复发件人和抄送/密件抄送的联系人。 转发- 将电子邮件的副本发送给其他收件人。 这几种情形分别在什么时候用呢&#xff1f; 回复 比如Alen给你…

Linux怎么查看boot目录的挂载分区

要查看 Linux 中 /boot 目录的挂载分区&#xff0c;可以使用以下命令&#xff1a; df -h /boot 这条命令将显示 /boot 目录所在的文件系统的相关信息&#xff0c;包括文件系统的设备、挂载点、容量、已用空间、可用空间和挂载类型等。 另外&#xff0c;你也可以通过查看 /etc/f…