03---java面试八股文——mybatis-------8题

news2024/11/26 16:41:41

21、MyBatis实现一对一查询

  1. MyBatis 有两种不同的方式加载关联:

    • 嵌套 Select 查询:通过执行另外一个 SQL 映射语句来加载期望的复杂类型。
    • 嵌套结果映射:使用嵌套的结果映射来处理连接结果的重复子集。
    • 查看mybatis的关联
      MyBatis是一种流行的Java持久化框架,它提供了多种方式来实现一对一关联。以下是几种常见的方式:
  2. 嵌套select查询(Nested Queries):这种方式通过在主查询中使用子查询来获取关联对象的数据。在MyBatis中,可以使用<select>标签嵌套另一个<select>标签来实现一对一关联查询。具体操作是在主查询中使用子查询获取关联对象的数据,并将其映射到主对象的属性中。

<resultMap id="blogResult" type="Blog">
  <association property="author" column="author_id" javaType="Author" select="selectAuthor"/>
</resultMap>

<select id="selectBlog" resultMap="blogResult">
  SELECT * FROM BLOG WHERE ID = #{id}
</select>

<select id="selectAuthor" resultType="Author">
  SELECT * FROM AUTHOR WHERE ID = #{id}
</select>
  1. 嵌套结果映射(Nested Result Maps):这种方式通过在结果映射中定义嵌套的结果映射来实现一对一关联。在MyBatis中,可以使用<resultMap>标签定义嵌套的结果映射,然后在主结果映射中引用它。具体操作是在主结果映射中使用<association>标签引用关联对象的结果映射。

    • 延迟加载(Lazy Loading):这种方式通过延迟加载关联对象的数据来实现一对一关联。在MyBatis中,可以使用<association>标签的fetchType属性设置为lazy来启用延迟加载。具体操作是在需要访问关联对象数据时才进行加载。
  2. 嵌套查询和嵌套结果映射的组合:有时候,可以将嵌套查询和嵌套结果映射结合起来使用,以实现更复杂的一对一关联查询。

在这里插入图片描述

22、MyBatis实现一对多查询有几种方式,怎么操作的?((关联(association))

MyBatis是一种Java持久层框架,它提供了多种方式来实现一对多的关系。以下是几种常见的方式及其操作方法:

  1. 嵌套select查询(Nested Queries):通过在主查询中嵌套子查询来获取关联对象的数据。在MyBatis的Mapper XML文件中,可以使用<collection>标签定义一个嵌套查询,通过指定子查询的SQL语句和结果映射关系来实现一对多的关系。

    示例代码:

<select id="selectPostsForBlog" resultType="Post">
  SELECT * FROM POST WHERE BLOG_ID = #{id}
</select>

<resultMap id="blogResult" type="Blog">
  <collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>
</resultMap>

<select id="selectBlog" resultMap="blogResult">
  SELECT * FROM BLOG WHERE ID = #{id}
</select>


1.1 . 延迟加载(Lazy Loading):在查询主对象时,不立即加载关联对象的数据,而是在需要使用关联对象时再进行加载。在MyBatis的Mapper XML文件中,可以使用<collection>标签的fetchType属性设置为lazy来实现延迟加载。

示例代码:

 <select id="selectPostsForBlog" resultType="Post">
  SELECT * FROM POST WHERE BLOG_ID = #{id}
</select>

<resultMap id="blogResult" type="Blog">
   <!-- collection标签的含义: posts 是一个存储 Post 的 ArrayList 集合-->
  <collection property="posts" javaType="ArrayList" column="id" fetchType="lazy" ofType="Post" select="selectPostsForBlog"/>
</resultMap>

<select id="selectBlog" resultMap="blogResult">
  SELECT * FROM BLOG WHERE ID = #{id}
</select>
  1. 嵌套结果映射(Nested Result Maps):通过在结果映射中定义嵌套的结果映射来实现一对多的关系。在MyBatis的Mapper XML文件中,可以使用<resultMap>标签中使用<collection>标签定义一个嵌套的结果映射。

    示例代码:

<select id="selectBlog" resultMap="blogResult">
  select
  B.id as blog_id,
  B.title as blog_title,
  B.author_id as blog_author_id,
  P.id as post_id,
  P.subject as post_subject,
  P.body as post_body,
  from Blog B
  left outer join Post P on B.id = P.blog_id
  where B.id = #{id}
</select>

<resultMap id="blogResult" type="Blog">
  <id property="id" column="blog_id" />
  <result property="title" column="blog_title"/>
  <collection property="posts" ofType="Post">
    <id property="id" column="post_id"/>
    <result property="subject" column="post_subject"/>
    <result property="body" column="post_body"/>
  </collection>
</resultMap>

这段代码和上面一段一样的作用

<select id="selectBlog" resultMap="blogResult">
  select
  B.id as blog_id,
  B.title as blog_title,
  B.author_id as blog_author_id,
  P.id as post_id,
  P.subject as post_subject,
  P.body as post_body,
  from Blog B
  left outer join Post P on B.id = P.blog_id
  where B.id = #{id}
</select>

<resultMap id="blogResult" type="Blog">
  <id property="id" column="blog_id" />
  <result property="title" column="blog_title"/>
  <collection property="posts" ofType="Post" resultMap="blogPostResult" columnPrefix="post_"/>
</resultMap>

<resultMap id="blogPostResult" type="Post">
  <id property="id" column="id"/>
  <result property="subject" column="subject"/>
  <result property="body" column="body"/>
</resultMap>

示例:一个用户上面有多个账户

public class User implements Serializable {
    private Integer id;
    private String username;
    private String address;
    private String sex;
    private Date birthday;

    //一对多关系映射:主表实体应该包含从表实体的集合引用
    private List<Account> accounts;
}


public class Account implements Serializable{
 	private Integer aid;
    private Integer uid;
    private Double money;
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.itheima.dao.IUserDao">

    <!--定义 user 的 resultMap -->
    <resultMap id="userAccountMap" type="user">
    
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="address" column="address"></result>
        <result property="sex" column="sex"></result>
        
        <!--配置user对象account集合的映射
            ofType集合中元素的类型-->
        <collection property="accounts" ofType="account" fetchType="lazy">
            <id column="aid" property="id" ></id>
            <result column="uid" property="uid"></result>
            <result column="money" property="money"></result>
        </collection>
        
    </resultMap>

    <!--配置查询所有-->
    <select id="findAll" resultMap="userAccountMap">
        select u.*, a.id as aid, a.uid, a.money from user u left outer join account a on u.id = a.uid
    </select>
    
</mapper>

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

  1. 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()方法的调用。这就是延迟加载的基本原理。

补充什么是 CGLIB?

  1. 什么是 CGLIB?
    • CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。
    • 通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB 是一个好的选择。
  2. CGLIB 的原理
    • 动态生成一个要代理类的子类,子类重写要代理的类的所有不是 final 的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
  3. CGLIB 底层:采用ASM字节码生成框架,使用字节码技术生成代理类,比使用 Java 反射效率要高。

24、Mybatis的一级、二级缓存:

  1. 一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
  2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable 序列化接口(可用来保存对象的状态),可在它的映射文件中配置<cache/>
  3. 对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。

25、什么是MyBatis的接口绑定?有哪些实现方式?

  1. 接口绑定,就是在MyBatis 中任意定义接口,然后把接口里面的方法和 SQL语句绑定, 我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置。
  2. 接口绑定有两种实现方式:
    • 一种是通过注解绑定,就是在接口的方法上面加上@Select、@Update 等注解,里面包含 Sql 语句来绑定;
    • 另外一种就是通过 xml里面写SQL来绑定, 在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名。当Sql语句比较简单时候,用注解绑定, 当SQL语句比较复杂时候,用 xml 绑定,一般用 xml 绑定的比较多。

26、Mapper编写有哪几种方式

  1. 第一种:接口实现类继承SqlSessionDaoSupport:使用此种方法需要编写mapper 接口,mapper 接口实现类、mapper.xml 文件。

1、在 MybatisConfig.xml 中配置 mapper.xml 的位置

<mappers>
 <mapper resource="mapper.xml 文件的地址" />
 <mapper resource="mapper.xml 文件的地址" />
 </mappers>

2、定义 mapper 接口
3、实现类继承SqlSessionDaoSupport ,mapper 方法中可以 this.getSqlSession()进行数据增删改查。
4、spring 配置

<bean id=" " class="mapper接口的实现类">
 <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
 </bean>
  1. 第二种:使用org.mybatis.spring.mapper.MapperFactoryBean:

1、在 MybatisConfig.xml 中配置 mapper.xml 的位置,如果 mapper.xml 和mappre 接口的名称相同且在同一个目录,这里可以不用配置

<mappers>
 <mapper resource="mapper.xml 文件的地址" />
 <mapper resource="mapper.xml 文件的地址" />
 </mappers>

2、定义 mapper 接口:
2.1、mapper.xml 中的 namespace 为 mapper 接口的地址
2.2、mapper 接口中的方法名和 mapper.xml 中的定义的 statement 的 id 保持一

3、Spring 中定义

<bean id="" class="org.mybatis.spring.mapper.MapperFactoryBean">
 <property name="mapperInterface" value="mapper接口地址" />
 <property name="sqlSessionFactory" ref="sqlSessionFactory" />
 </bean>
  1. 第三种:使用mapper 扫描器:

1、mapper.xml 文件编写:
mapper.xml 中的 namespace 为 mapper 接口的地址;
mapper 接口中的方法名和 mapper.xml 中的定义的 statement 的 id 保持一致;
如果将mapper.xml和mapper接口的名称保持一致则不用在Mybatis.xml中进行配置。

2、定义 mapper 接口:
注意mapper.xml 的文件名和 mapper 的接口名称保持一致,且放在同一个目录

3、配置 mapper 扫描器:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
 <property name="basePackage" value="mapper 接口包地址"></property>
 <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
 </bean>

4、使用扫描器后从spring 容器中获取 mapper的实现对象

27、使用MyBatis的mapper接口调用时有哪些要求?

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

28、简述Mybatis的插件运行原理,以及如何编写一个插件。

  1. Mybatis 仅可以编写针对 ParameterHandler、ResultSetHandler、StatementHandler、Executor 这 4 种接口的插件,Mybatis 使用 JDK 的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler 的 invoke()方法,当然,只会拦截那些你指定需要拦截的方法。
  2. 编写插件:实现Mybatis 的 Interceptor 接口并复写 intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。

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

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

相关文章

FME学习之旅---day16

我们付出一些成本&#xff0c;时间的或者其他&#xff0c;最终总能收获一些什么。 【FME-HOW-TO系列】24 拓扑相交 本章还是学习SpatialFilter转换器得用法&#xff0c;主要用到的空间关系是相交&#xff0c;即Filter Intersect Candidate。 首先&#xff0c;添加读模块的相…

ssm框架笔记-maven

html是骨头 css使皮肤 js是你能做的动作 MAVEN 依赖管理&#xff1a;1.声明dependenciys标签 2.maven search3。 版本号提取 3.$引用 3.2依赖传递和冲突 依赖传递指的是当一个模块或库 A 依赖于另一个模块或库 B&#xff0c;而 B 又依赖于模块或库 C&#xff0c;那么 A 会间…

基于SSM的戒烟网站(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的戒烟网站&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring SpringMv…

算法打卡day21(开始回溯)

今日任务&#xff1a; 1&#xff09;77.组合 77.组合 题目链接&#xff1a;77. 组合 - 力扣&#xff08;LeetCode&#xff09; 文章讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;带你学透回溯算法-组合问题&#xff08;对应力扣题目&#xff1a;77…

第一次给开源项目做贡献,我给 Hutool 改了行注释

大家好&#xff0c;我是松柏。 前两天在修 bug 的时候&#xff0c;写了个indexOf的方法。 这个方法是用来获取一段文本中某个字符串第 n 次出现的索引&#xff0c; 由于第一次写这个方法的时候少考虑了一种边界条件&#xff0c;导致最后查出的数据有时候会不符合预期。 我处…

【跟着CHATGPT学习硬件外设 | 03】UART

本文根据博主设计的Prompt由CHATGPT生成&#xff0c;形成极简外设概念。 &#x1f680; 1. 概念揭秘 UART&#xff0c;全称为"Universal Asynchronous Receiver/Transmitter"&#xff08;通用异步收发器&#xff09;&#xff0c;是一种常用的串行通信协议。UART最早…

AI学习-Pandas数据处理分析

文章目录 1. Pandas概述2. Series用法2.1 Series的创建2.2 Series的取值2.3 Series的相关方法 3. DataFrame用法3.1 DataFrame创建3.2 DataFrame取值3.3 DataFrame相关方法 1. Pandas概述 ​ Pandas 是一个开源的数据分析处理库&#xff0c;它应用在数据科学、统计分析、机器学…

2006-2023年2月各地级市城投债详细数据

2006-2023.2各地级市城投债详细数据 1、时间&#xff1a;2006-2023.2 2、来源&#xff1a;深圳证券交易所和上海证券交易所官网、人民银行、证券监督管理委员会等金融监管机构等官网 3、指标&#xff1a;省份、城市、证券代码、证券简称、债券简称、证券全称、债券初始面值单…

应急响应靶机训练-Linux2题解

前言 接上文&#xff0c;应急响应靶机训练Linux2 靶机地址&#xff1a;应急响应靶机-Linux(2) 题解 登录虚拟机&#xff1a; 修改面板密码 提交攻击者IP 答案&#xff1a;192.168.20.1 查看宝塔日志即可 用的net直接是网关 提交攻击者修改的管理员密码(明文) 答案&…

QA:ubuntu22.04.4桌面版虚拟机鼠标丢失的解决方法

前言 在Windows11中的VMWare Workstation17.5.1 Pro上安装了Ubuntu22.04.4&#xff0c;在使用过程中发现&#xff0c;VM虚拟机的鼠标的光标会突然消失&#xff0c;但鼠标其他正常&#xff0c;就是光标不见了&#xff0c;下面是解决办法。 内容 如下图&#xff0c;输入mouse&a…

Java多线程三种实现方式

一、继承Thread方法 public class MyThread extends Thread{Overridepublic void run() {for (int i 0; i < 10; i) {System.out.println(getName() "输出内容");}}public static void main(String[] args) {MyThread thread1 new MyThread();MyThread thread…

【UI框架】——保姆式使用教程

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

leetCode刷题 22. 括号生成

目录 思路 解题方法 复杂度 code 题目&#xff1a; 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用于能够生成所有可能的并且 有效的 括号组合。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;["((()))","(()())"…

Docker 哲学 - Dockerfile 指令

Dockerfile 的 entrypoint 和 cmd 书写方式一样吗&#xff0c;分别用一个node项目的 demo来举例 Dockerfile 的 entrypoint 、cmd 有什么区别&#xff0c;分别举例他们同时出现的场景和 单独出现的场景 entrypoint 和 cmd 命令&#xff1a; 同时出现&#xff1a; 1、cmd 作为 e…

静态住宅IP好用吗?怎么选择?

在进行海外 IP 代理时&#xff0c;了解动态住宅 IP 和静态住宅 IP 的区别以及如何选择合适的类型非常重要。本文将介绍精态住宅 IP 特点和&#xff0c;并提供选择建议&#xff0c;帮助您根据需求做出明智的决策。 静态住宅 IP 的特点 静态住宅 IP 是指 IP 地址在一段时间内保…

uniapp 中引入第三方组件后,更改组件的样式 -使用/deep/不生效

在我们使用Vue搭建项目的时候&#xff0c;我们经常会用到一些UI框架&#xff0c;如Element&#xff0c;iView&#xff0c;但是有时候我们又想去修改Ul框架的样式&#xff0c;当我们修改样式失败的时候&#xff0c;可以尝试一下/deep/&#xff0c;亲测有效。 那失败的原因是什么…

Java数据结构-链表OJ题

目录 1. 移除链表元素2. 反转链表3. 返回中间结点4. 返回倒数第k个结点5. 合并两个有序链表6. 分割链表7. 回文链表8. 找相交链表的公共结点9. 判断链表是否有环10. 返回链表环的入口 老铁们好&#xff0c;学习完链表这个数据结构之后&#xff0c;怎么能少了OJ题呢&#xff1f;…

下载及安装PHP,composer,phpstudy,thinkPHP6.0框架

文章目录 目录 文章目录 前言 一、下载PHP 二、下载composer 三、下载PHPstudy 四、下载think PHP 1.下载 2.多应用开发 前言 thinkPHP是一款开源的PHP框架&#xff0c;它是基于MVC&#xff08;Model-View-Controller&#xff09;设计模式构建的。thinkPHP提供了丰富的…

牛客NC30 缺失的第一个正整数【simple map Java,Go,PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/50ec6a5b0e4e45348544348278cdcee5 核心 Map参考答案Java import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可…

【跟着CHATGPT学习硬件外设 | 01】SPI

文章目录 &#x1f680; 概念揭秘关键精华&#x1f31f; 秒懂案例生活类比实战演练 &#x1f50d; 原理与工作流程探秘步骤1&#xff1a;初始化SPI接口步骤2&#xff1a;主设备启动通信步骤3&#xff1a;主设备发送数据步骤4&#xff1a;从设备接收数据步骤5&#xff1a;从设备…