每日五道java面试题之mybatis篇(六)

在这里插入图片描述

目录:

  • 第一题. MyBatis⽀持动态SQL吗?
  • 第二题. 说说Mybatis的⼀级、⼆级缓存?
  • 第三题. MyBatis的功能架构是什么样的?
  • 第四题. 为什么Mapper接⼝不需要实现类?
  • 第五题. 说说Mybatis的插件运⾏原理,如何编写⼀个插件?

第一题. MyBatis⽀持动态SQL吗?

MyBatis中有⼀些⽀持动态SQL的标签,它们的原理是使⽤OGNL从SQL参数对象中计算表达式的值,根据表达式的值动态拼接SQL,以此来完成动态SQL的功能。

  • if
    根据条件来组成where⼦句
<select id="findActiveBlogWithTitleLike"
 resultType="Blog">
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’
<if test="title != null">
 AND title like #{title}
</if>
</select>
  • choose (when, otherwise)
    这个和Java 中的 switch 语句有点像
<select id="findActiveBlogLike"
 resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
 <when test="title != null">
 AND title like #{title}
 </when>
 <when test="author != null and author.name != null">
 AND author_name like #{author.name}
 </when>
 <otherwise>
 AND featured = 1
 </otherwise>
</choose>
</select>
  • trim (where, set)
  • < where>可以⽤在所有的查询条件都是动态的情况
<select id="findActiveBlogLike"
 resultType="Blog">
SELECT * FROM BLOG
<where>
 <if test="state != null">
 state = #{state}
 </if>
 <if test="title != null">
 AND title like #{title}
 </if>
 <if test="author != null and author.name != null">
 AND author_name like #{author.name}
 </if>
</where>
</select>
  • < set> 可以⽤在动态更新的时候
<update id="updateAuthorIfNecessary">
 update Author
 <set>
 <if test="username != null">username=#{username},</if>
 <if test="password != null">password=#{password},</if>
 <if test="email != null">email=#{email},</if>
 <if test="bio != null">bio=#{bio}</if>
 </set>
 where id=#{id}
</update>
  • foreach
    看到名字就知道了,这个是⽤来循环的,可以对集合进⾏遍历
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
<where>
 <foreach item="item" index="index" collection="list"
 open="ID in (" separator="," close=")" nullable="true">
 #{item}
 </foreach>
</where>
</select>

第二题. 说说Mybatis的⼀级、⼆级缓存?

  1. ⼀级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作⽤域为SqlSession,各个SqlSession之间的缓存相互隔离,当 Session flush 或 close 之后,该 SqlSession 中的所有 Cache 就将清空,MyBatis默认打开⼀级缓存。

在这里插入图片描述

  1. ⼆级缓存与⼀级缓存其机制相同,默认也是采⽤ PerpetualCache,HashMap 存储,不同之处在于其存储作⽤域为Mapper(Namespace),可以在多个SqlSession之间共享,并且可⾃定义存储源,如 Ehcache。默认不打开⼆级缓存,要开启⼆级缓存,使⽤⼆级缓存属性类需要实现Serializable序列化接⼝(可⽤来保存对象的状态),可在它的映射⽂件中配置。

在这里插入图片描述

第三题. MyBatis的功能架构是什么样的?

在这里插入图片描述
我们⼀般把Mybatis的功能架构分为三层:

  • API接⼝层:提供给外部使⽤的接⼝API,开发⼈员通过这些本地API来操纵数据库。接⼝层⼀接收到调⽤请求就会调⽤数据处理层来完成具体的数据处理。
  • 数据处理层:负责具体的SQL查找、SQL解析、SQL执⾏和执⾏结果映射处理等。它主要的⽬的是根据调⽤的请求完成⼀次数据库操作。
  • 基础⽀撑层:负责最基础的功能⽀撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共⽤的东⻄,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的⽀撑。

第四题. 为什么Mapper接⼝不需要实现类?

四个字回答:动态代理,我们来看⼀下获取Mapper的过程:
在这里插入图片描述
获取Mapper

我们都知道定义的Mapper接⼝是没有实现类的,Mapper映射其实是通过动态代理实现的

BlogMapper mapper = session.getMapper(BlogMapper.class);

七拐⼋绕地进去看⼀下,发现获取Mapper的过程,需要先获取MapperProxyFactory——Mapper代理⼯⼚。

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
 MapperProxyFactory<T> mapperProxyFactory =
(MapperProxyFactory)this.knownMappers.get(type);
 if (mapperProxyFactory == null) {
 throw new BindingException("Type " + type + " is not known to the
MapperRegistry.");
 } else {
 try {
 return mapperProxyFactory.newInstance(sqlSession);
 } catch (Exception var5) {
 throw new BindingException("Error getting mapper instance. Cause: " + var5,
var5);
 }
 }
}

MapperProxyFactory

MapperProxyFactory的作⽤是⽣成MapperProxy(Mapper代理对象)。

public class MapperProxyFactory<T> {
 private final Class<T> mapperInterface;
 ……
 protected T newInstance(MapperProxy<T> mapperProxy) {
 return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]
{this.mapperInterface}, mapperProxy);
 }
 public T newInstance(SqlSession sqlSession) {
 MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface,
this.methodCache);
 return this.newInstance(mapperProxy);
 }
}

这⾥可以看到动态代理对接⼝的绑定,它的作⽤就是⽣成动态代理对象(占位),⽽代理的⽅法被放到了MapperProxy中。

MapperProxy
MapperProxy⾥,通常会⽣成⼀个MapperMethod对象,它是通过cachedMapperMethod⽅法对其进⾏初始化的,然后执⾏excute⽅法。

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 try {
 return Object.class.equals(method.getDeclaringClass()) ? method.invoke(this,
args) : this.cachedInvoker(method).invoke(proxy, method, args, this.sqlSession);
 } catch (Throwable var5) {
 throw ExceptionUtil.unwrapThrowable(var5);
 }
}

MapperMethod
MapperMethod⾥的excute⽅法,会真正去执⾏sql。这⾥⽤到了命令模式,其实绕⼀圈,最终它还是通过SqlSession的实例去运⾏对象的sql。

public Object execute(SqlSession sqlSession, Object[] args) {
 Object result;
 Object param;
 ……
 case SELECT:
 if (this.method.returnsVoid() && this.method.hasResultHandler()) {
 this.executeWithResultHandler(sqlSession, args);
 result = null;
 } else if (this.method.returnsMany()) {
 result = this.executeForMany(sqlSession, args);
 } else if (this.method.returnsMap()) {
 result = this.executeForMap(sqlSession, args);
 } else if (this.method.returnsCursor()) {
 result = this.executeForCursor(sqlSession, args);
 } else {
 param = this.method.convertArgsToSqlCommandParam(args);
 result = sqlSession.selectOne(this.command.getName(), param);
 if (this.method.returnsOptional() && (result == null ||
!this.method.getReturnType().equals(result.getClass()))) {
 result = Optional.ofNullable(result);
 }
 }
 break;
 ……
 }

第五题. 说说Mybatis的插件运⾏原理,如何编写⼀个插件?

插件的运⾏原理?

Mybatis会话的运⾏需要ParameterHandler、ResultSetHandler、StatementHandler、Executor这四⼤对象的配合,插件的原理就是在这四⼤对象调度的时候,插⼊⼀些我我们⾃⼰的代码。
在这里插入图片描述
Mybatis使⽤JDK的动态代理,为⽬标对象⽣成代理对象。它提供了⼀个⼯具类 Plugin ,实现了InvocationHandler 接⼝。
在这里插入图片描述
使⽤ Plugin ⽣成代理对象,代理对象在调⽤⽅法的时候,就会进⼊invoke⽅法,在invoke⽅法中,如果存在签名的拦截⽅法,插件的intercept⽅法就会在这⾥被我们调⽤,然后就返回结果。如果不存在签名⽅法,那么将直接反射调⽤我们要执⾏的⽅法。

如何编写⼀个插件?
我们⾃⼰编写MyBatis 插件,只需要实现拦截器接⼝ Interceptor (org.apache.ibatis. pluginInterceptor ) ,在实现类中对拦截对象和⽅法进⾏处理。

  • 实现Mybatis的Interceptor接⼝并重写intercept()⽅法这⾥我们只是在⽬标对象执⾏⽬标⽅法的前后进⾏了打印;
public class MyInterceptor implements Interceptor {
 Properties props=null;
 @Override
 public Object intercept(Invocation invocation) throws Throwable {
 System.out.println("before……");
 //如果当前代理的是⼀个⾮代理对象,那么就会调⽤真实拦截对象的⽅法
 // 如果不是它就会调⽤下个插件代理对象的invoke⽅法
 Object obj=invocation.proceed();
 System.out.println("after……");
 return obj;
 }
}
  • 然后再给插件编写注解,确定要拦截的对象,要拦截的⽅法
@Intercepts({@Signature(
 type = Executor.class, //确定要拦截的对象
 method = "update", //确定要拦截的⽅法
 args = {MappedStatement.class,Object.class} //拦截⽅法的参数
)})
public class MyInterceptor implements Interceptor {
 Properties props=null;
 @Override
 public Object intercept(Invocation invocation) throws Throwable {
 System.out.println("before……");
 //如果当前代理的是⼀个⾮代理对象,那么就会调⽤真实拦截对象的⽅法
 // 如果不是它就会调⽤下个插件代理对象的invoke⽅法
 Object obj=invocation.proceed();
 System.out.println("after……");
 return obj;
 }
}
  • 最后,再MyBatis配置⽂件⾥⾯配置插件
<plugins>
 <plugin interceptor="xxx.MyPlugin">
 <property name="dbType",value="mysql"/>
 </plugin>
</plugins>

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GEE入门及进阶教程|使用表达式处理图像

目录 1.EVI的算术计算 2.使用表达式计算 EVI 3.使用表达式计算 BAI 1.EVI的算术计算 增强植被指数 (EVI) 旨在最大限度地减少 NDVI 的饱和度和其他问题&#xff0c;在叶绿素含量高的地区&#xff08;例如雨林&#xff09;&#xff0c;EVI 不会像 NDVI 那样饱和&#xff08;即…

转置卷积(transposed-conv)

一、什么是转置卷积 1、转置卷积的背景 通常&#xff0c;对图像进行多次卷积运算后&#xff0c;特征图的尺寸会不断缩小。而对于某些特定任务 (如图像分割和图像生成等)&#xff0c;需将图像恢复到原尺寸再操作。这个将图像由小分辨率映射到大分辨率的尺寸恢复操作&#xff0c…

spring boot3登录开发-2(2短信验证码接口实现)

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 &#x1f30a;山高路远&#xff0c;行路漫漫&#xff0c;终有归途 目录 写在前面 上文衔接 内容简介 短信验证码接口实现 1.依赖导入 2.接口分析 3.实现思路 3.功能实现 创建发送短信…

USART串口控制LED灯

#include "uart4.h"void uart4_init() {//使能GPIORCC->MP_AHB4ENSETR |(0x1<<1);RCC->MP_AHB4ENSETR |(0x1<<6);//使能UART4RCC->MP_APB1ENSETR |(0x1<<16) ;//GPIO MODER设置 复用模式设置GPIOB->MODER |(0x2<<4);G…

C语言例:设 int i=2;float f=14;,则执行语句f=(float)i; 后。变量i 的值

代码如下&#xff1a; #include<stdio.h> int main(void) {int i2;float f14;f(float)i;printf("i %d\n",i); //i2//强制转换不会改变数据类型printf("i %.1f\n",i);return 0; } 结果如下&#xff1a;

【Leetcode每日一题】 递归 - 两两交换链表中的节点(难度⭐)(38)

1. 题目解析 题目链接&#xff1a;24. 两两交换链表中的节点 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 一、理解递归函数的含义 首先&#xff0c;我们需要明确递归函数的任务&#xff1a;给定一个链表&#xf…

网速监控,实时网络速度监控

带宽与网速 现在&#xff0c;对高带宽的需求空前高涨&#xff0c;而且网络&#xff08;包括标准的内部部署&#xff09;以及公共、私有和混合环境都变得更加复杂。 虽然带宽和网速经常互换使用&#xff0c;但它们并不总是相同的。网速更多的是与延迟有关&#xff0c;而不是与…

es 集群核心概念以及实践

节点概念&#xff1a; 节点是一个Elasticsearch的实例 本质上就是一个JAVA进程一台机器上可以运行多个Elasticsearch进程&#xff0c;但是生产环境一般建议一台机器上只运行一个Elasticsearch实例 每一个节点都有名字&#xff0c;通过配置文件配置&#xff0c;或者启动时候 -…

2024年【T电梯修理】模拟考试及T电梯修理模拟考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 T电梯修理模拟考试是安全生产模拟考试一点通生成的&#xff0c;T电梯修理证模拟考试题库是根据T电梯修理最新版教材汇编出T电梯修理仿真模拟考试。2024年【T电梯修理】模拟考试及T电梯修理模拟考试题库 1、【多选题】…

​CNC数控机床能否通过工业智能网关实现远程运维​?-天拓四方

随着工业4.0时代的来临&#xff0c;智能制造成为制造业转型升级的关键。CNC数控机床作为制造业的核心设备之一&#xff0c;其智能化、远程化的运维管理显得尤为重要。工业智能网关作为一种连接物理世界与数字世界的桥梁&#xff0c;为CNC数控机床的远程运维提供了强大的技术支撑…

急!苹果手机充电充不进去什么原因?

在使用苹果手机时&#xff0c;有时可能会遇到充电问题&#xff0c;即充电时无法正常充电的情况。这种情况可能会导致手机无法充电&#xff0c;影响手机的正常使用。虽然苹果手机通常具有良好的充电性能&#xff0c;但是出现充电问题也并非罕见。 在本文中&#xff0c;我们将探…

若依添加页面

背景&#xff1a;我想增加的是一个收支管理的页面 views中直接添加income文件夹&#xff0c;里面放着index.vue 网页的菜单中添加这个页面的菜单

【JavaScript】JavaScript 程序流程控制 ③ ( 对 JavaScript 代码进行断点调试 )

文章目录 一、对 JavaScript 代码进行断点调试1、断点调试2、浏览器断点调试 一、对 JavaScript 代码进行断点调试 1、断点调试 断点调试 指的是 在 程序代码 的 指定行 设置一个断点 , 以 调试模式 启动后 , 当程序运行到 断点 处 , 就会阻塞住 , 此时可以查看 当前 各个变量的…

GraalVM详细安装及打包springboot、java、javafx使用教程(打包普通JAVA项目篇)

前言 在当前多元化开发环境下&#xff0c;Java作为一种广泛应用的编程语言&#xff0c;其应用部署效率与灵活性的重要性日益凸显。Spring Boot框架以其简洁的配置和强大的功能深受开发者喜爱&#xff0c;而JavaFX则为开发者提供了构建丰富桌面客户端应用的能力。然而&#xff…

中国网怎么投稿,发稿流程,中国网发稿需要多少钱?(附中国网各频道价格明细)

中国网是一家专业的新闻媒体平台&#xff0c;拥有庞大的读者群体和高质量的新闻内容。很多企业和个人都希望能够在中国网上发布自己的文章或新闻&#xff0c;以增加曝光度和影响力。那么&#xff0c;中国网如何投稿&#xff1f;发稿流程是怎样的&#xff1f;又需要多少费用呢&a…

从初学者到专家:Java的Lambda表达式完整指南

一.Lambda的概念 概念&#xff1a;Lambda表达式是Java 8引入的一项重要功能&#xff0c;它允许我们以更简洁和灵活的方式编写代码。可以把Lambda表达式看作是一种更方便的匿名函数&#xff0c;可以像数据一样传递和使用。 使用Lambda表达式可以让我们写出更短、更易读的代码。…

[28000][1045] Access denied for user ‘ ‘ (using password: YES)

这个错误看了一上午&#xff0c;始终是没找到原因。但是进过不懈尝试还是找到答案。 问题&#xff1a; 问题1&#xff1a;发现host输入的IP与真实连接的地址IP不一致。 问题2&#xff1a;报错如何解决。 答案&#xff1a;因为你的账号和密码输入的不正确&#xff0c;导致去连…

pstree 进程树

pstree -aup a是所有all u是用户user p是pid进程号

python基本概念和基本数据类型

一、基本概念 1.变量 变量是编程语言中最基本的概念&#xff0c;和字面意思一样&#xff0c;指的就是他们的值可变&#xff0c;和我们以前学习的方程类似&#xff0c;变量可以代入任何值。 命名规范&#xff1a;变量一般使用&#xff1a; 英文字母、下划线 和 数字组成 2.关键…

【JSON2WEB】10 基于 Amis 做个登录页面login.html

【JSON2WEB】01 WEB管理信息系统架构设计 【JSON2WEB】02 JSON2WEB初步UI设计 【JSON2WEB】03 go的模板包html/template的使用 【JSON2WEB】04 amis低代码前端框架介绍 【JSON2WEB】05 前端开发三件套 HTML CSS JavaScript 速成 【JSON2WEB】06 JSON2WEB前端框架搭建 【J…