颍上人才网
颍上职场资讯
颍上面试技巧
正文:Java面试题精选:深入理解#{}和${}的区别与用法
Java面试题精选:深入理解#{}和${}的区别与用法
来源:网络整理2025-03-04

[id_2014774084]

面试刷图,查缺补漏

往期面试题,以 10 篇为一个单位,已归置到本公众号菜单栏的“面试题”中,有需要的可以进行翻阅。

[id_195[id_1520569432]44186]

答:${}在 Properties 文件中是变量占位符,可用于标签属性值以及 sql 内部,属于静态文本替换。例如,${driver}会被静态替换为 com.mysql.jdbc.Driver。

#{}是 sql 的参数占位符,Mybatis 会把 sql 中的#{}替换成?号,在 sql 执行之前,会利用 PreparedStatement 的参数设置方法,按照顺序给 sql 的?号占位符设置参数值,例如 ps.setInt(0, parameterValue),#{item.name}的取值方式是通过反射从参数对象中获取 item 对象的 name 属性值,就如同 param.getItem().getName()一样。

Xml 映射文件中,常见的标签有 select、insert、update、delete 等。那么,除了这些常见标签之外,还有哪些其他标签呢?

答:还有很多其他的标签,、

加上动态 sql 的 9 个标签,分别是 trim、where、set、foreach、if、choose、when、otherwise、bind 等。其中,这些标签有的是为 sql 片段而设,可通过标签引入 sql 片段;有的是为不支持自增的主键生成策略而设。

在最佳实践中,一般一个 Xml 映射文件会对应写一个 Dao 接口。请问,这个 Dao 接口的工作原理是什么呢?当 Dao 接口里的方法参数不同时,这些方法能够重载吗?

Dao 接口,也就是人们通常所说的 Mapper 接口。接口的全限名,就是映射文件中的 namespace 的值。接口的方法名,是映射文件中 MappedStatement 的 id 值。接口方法内的参数,是传递给 sql 的参数。

Mapper 接口是不存在实现类的。当对接口方法进行调用时,会将接口的全限名与方法名拼接成字符串,以此作为 key 值,能够唯一地定位到一个 MappedStatement。例如,com.mybatis3.mappers.StudentDao.findStudentById 这个字符串,可以唯一地找到 namespace 为 com.mybatis3.mappers.StudentDao 且 id 为 findStudentById 的 MappedStatement。Mybatis 里,每一个特定的标签,都会被转化为一个 MappedStatement 对象。

Dao 接口里的方法不能进行重载。这是因为它采用的是全限名加方法名的保存和寻找策略。

Dao 接口的工作原理为 JDK 动态代理。Mybatis 在运行时会利用 JDK 动态代理来为 Dao 接口生成代理 proxy 对象。这个代理对象 proxy 会对接口方法进行拦截。接着,它会转而执行由 MappedStatement 所代表的 sql。最后,将 sql 执行的结果返回。

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

Mybatis 通过 RowBounds 对象来实现分页。它对 ResultSet 结果集进行内存分页,而非物理分页。既可以在 sql 中直接书写带有物理分页的参数以完成物理分页功能,也可以借助分页插件来完成物理分页。

分页插件的基本原理在于利用 Mybatis 所提供的插件接口,进而实现自定义的插件。在该插件的拦截方法当中,能够拦截到待执行的 sql 。之后可以对 sql 进行重写,并且依据 dialect 方言,添加与之对应的物理分页语句以及物理分页参数。

从 student 表中选择所有列,将其作为子查询并给子查询结果起个别名 t,然后从 t 表中选择前 10 行数据。

简述 Mybatis 的插件运行原理,并且说明怎样去编写一个插件。

Mybatis 能够编写针对 ParameterHandler、ResultSetHandler、StatementHandler、Executor 这 4 种接口的插件。它利用 JDK 的动态代理,为需要拦截的接口生成代理对象,从而实现接口方法的拦截功能。每当执行这 4 种接口对象的方法时,就会进入拦截方法,也就是 InvocationHandler 的 invoke()方法。并且,只会拦截那些你指定需要拦截的方法。

实现 Mybatis 的 Interceptor 接口,接着复写 intercept()方法。之后为插件编写注解,明确要拦截某一个接口的哪些方法。需要记住,一定不要忘记在配置文件中配置所编写的插件。

6、Mybatis执行批量插入,能返回数据库主键列表吗?

答:能,JDBC都能,Mybatis当然也能。

Mybatis 动态 sql 是用来做什么的呢?它都包含哪些动态 sql 呢?能否简单阐述一下动态 sql 的执行原理呢?

Mybatis 动态 sql 能够让我们在 Xml 映射文件内部,以标签的形式来编写动态 sql 。通过这种方式,我们可以完成逻辑判断以及动态拼接 sql 的功能。Mybatis 提供了 9 种动态 sql 标签,分别是 trim、where、set、foreach、if、choose、when、otherwise、bind 。

其执行原理是,利用 OGNL 从 sql 参数对象里去计算表达式的值,接着依据表达式的值把 sql 进行动态拼接,通过这样的方式来达成动态 sql 的功能。

Mybatis 是怎样把 sql 执行的结果封装成目标对象并且进行返回的呢?它都有哪些不同的映射形式呢?

使用标签,将列名和对象属性名之间的映射关系逐一进行定义。第二种方式是利用 sql 列的别名功能,把列别名写成对象属性名,像 T_NAME AS NAME 这样。通常对象属性名是 name 且为小写,但列名是不区分大小写的。Mybatis 会忽略列名的大小写,能够智能地找到与之对应的对象属性名。甚至你写成 T_NAME AS NaMe,Mybatis 也能正常工作。

有了列名与属性名的映射关系之后,Mybatis 会通过反射来创建对象。并且,它会利用反射给对象的属性逐个进行赋值,然后将赋值后的对象返回。然而,如果存在找不到映射关系的属性,那么这些属性就无法完成赋值。

Mybatis 能否执行一对一和一对多的关联查询呢?它有哪些实现方式呢?这些实现方式之间又有哪些区别呢?

Mybatis 可以执行一对一的关联查询,也可以执行一对多的关联查询,还能执行多对一的关联查询以及多对多的关联查询。多对一查询实际上就是一对一查询,只需将 selectOne()修改为 selectList();多对多查询实际上就是一对多查询,只需将 selectOne()修改为 selectList()。

关联对象查询有两种实现方式。其一,单独发送一个 sql 去查询关联对象,将其赋给主对象,接着返回主对象。其二,使用嵌套查询,嵌套查询的意思是使用 join 查询,其中一部分列是 A 对象的属性值,另一部分列是关联对象 B 的属性值,这样的好处是只需发送一个 sql 查询,就能把主对象及其关联对象都查出来。

那么问题出现了,join 查询得到了 100 条记录。要确定主对象是 5 个而不是 100 个,其去重复的原理在于标签内的子标签指定了能唯一确定一条记录的 id 列。Mybatis 会依据该列值来实现 100 条记录的去重复功能,并且可以有多个,这代表了联合主键的含义。

主对象的关联对象会依据这个原理进行重复。通常情况下,只有主对象会有重复记录,而关联对象一般不会重复。

下面的 join 查询得出了 6 条记录,其中第一列和第二列是 Teacher 对象的列,第三列是 Student 对象的列。Mybatis 进行去重复处理后,结果是 1 个老师和 6 个学生,并非 6 个老师和 6 个学生。

[id_1764971942]

teacher

38

teacher

39

teacher

40

teacher

41

teacher

42

teacher

43

mybatis面试问题_面试问题有哪些_面试问题提问技巧

Mybatis 是否具备延迟加载的功能?倘若具备,那么它的实现原理究竟是什么?

Mybatis 只支持 association 关联对象以及 collection 关联集合对象的延迟加载。其中,association 指的是一对一的关系,collection 指的是一对多的查询。在 Mybatis 的配置文件中,能够配置是否启用延迟加载,其方式为 lazyLoadingEnabled=true 或者 lazyLoadingEnabled=false。

它的原理在于,利用 CGLIB 来创建目标对象的代理对象。当对目标方法进行调用时,会进入拦截器方法。例如,当调用 a.getB().getName()时,拦截器的 invoke()方法察觉到 a.getB()为 null 值,此时就会单独发送之前保存好的用于查询关联 B 对象的 sql,将 B 查询出来,接着调用 a.setB(b),这样 a 的对象 b 属性就有了值,随后便可完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。

当然了,不只是 Mybatis ,几乎所有的,像 Hibernate 这类支持延迟加载的,其原理都是相同的。

在 Mybatis 的 Xml 映射文件里,不同的 Xml 映射文件,其 id 是否可以重复呢?

不同的 Xml 映射文件,若配置了 namespace,其 id 便可重复;若未配置 namespace,其 id 则不能重复;因为 namespace 并非必须,而只是一种最佳实践罢了。

原因是 namespace + id 被用作 Map 的 key 。如果没有 namespace ,就仅剩下 id 。这样一来,id 重复就会致使数据相互覆盖。而有了 namespace 后,自然 id 就能够重复,并且 namespace 不同的话,namespace + id 自然也就不同。

12、Mybatis中如何执行批处理?

答:使用BatchExecutor完成批处理。

Mybatis 有哪些执行器呢?它们之间存在着怎样的区别呢?

Mybatis 存在三种基本的 Executor 执行器,分别是 SimpleExecutor 、ReuseExecutor 以及 BatchExecutor 。

SimpleExecutor 每执行一次 update 操作时,就会开启一个 Statement 对象,执行完后立刻将其关闭;每执行一次 select 操作时,同样会开启一个 Statement 对象,执行完后也会立刻将其关闭。

执行 update 或 select 操作,通过 sql 作为 key 去查找 Statement 对象。如果存在该对象就直接使用,若不存在则创建一个新的。使用完之后,不会关闭该 Statement 对象,而是将其放置在 Map 内,以便下一次使用。简单来说,就是对 Statement 对象进行重复使用。

BatchExecutor 执行 update 操作,因为 JDBC 批处理不支持 select,所以这里没有 select。它会将所有的 sql 都添加到批处理中,通过 addBatch()方法来实现。然后等待统一执行,使用 executeBatch()方法。它缓存了多个 Statement 对象,每个 Statement 对象都是在 addBatch()完毕后,等待逐一执行 executeBatch()的批处理操作。与JDBC批处理相同。

Executor 具有的这些特点,是被严格限定在 SqlSession 的生命周期范围之内的。

在 Mybatis 中怎样去指定使用哪一种 Executor 执行器呢?

在 Mybatis 的配置文件里,能够指定默认的 ExecutorType 执行器类型。同时,还可以手动给 DefaultSqlSessionFactory 用于创建 SqlSession 的方法传递 ExecutorType 类型的参数。

15、Mybatis是否可以映射Enum枚举类?

Mybatis 能够映射枚举类,并且不仅仅局限于映射枚举类,它还可以将任何对象映射到表的一列上。其映射方式是自定义一个 TypeHandler,通过实现 TypeHandler 的 setParameter()和 getResult()接口方法来完成映射。

TypeHandler 有两个作用,其一为完成从 javaType 到 jdbcType 的转换;其二为完成从 jdbcType 到 javaType 的转换,这体现在 setParameter()和 getResult()这两个方法上,其中 setParameter()方法代表设置 sql 问号占位符参数,getResult()方法代表获取列查询结果。

Mybatis 映射文件里,若 A 标签通过 include 引用了 B 标签的内容,那么 B 标签能否在 A 标签之后定义呢?还是说必须在 A 标签之前定义?

Mybatis 解析 Xml 映射文件是按顺序进行的。然而,被引用的 B 标签即便定义在任何地方,Mybatis 也能够正确识别。

原理是,Mybatis 会对 A 标签进行解析。在解析过程中,它发现 A 标签引用了 B 标签,然而此时 B 标签还未被解析到,也就是说 B 标签尚不存在。基于这种情况,Mybatis 会把 A 标签标记为未解析状态,接着继续解析余下的标签,其中就包含 B 标签。当所有标签都解析完毕后,Mybatis 会重新对那些被标记为未解析的标签进行解析。在再次解析 A 标签时,因为 B 标签已经存在了,所以 A 标签就能够正常解析完成了。

简述 Mybatis 的 Xml 映射文件与 Mybatis 内部数据结构之间存在怎样的映射关系?

Mybatis 把所有的 Xml 配置信息都包裹在了 All-In-One 这种重量级的对象 Configuration 的内部。在 Xml 映射文件当中,

标签会被解析成 ParameterMap 对象,并且它的每个子元素都会被解析成 ParameterMapping 对象。

标签会被解析成 ResultMap 对象,它的每个子元素会被解析成 ResultMapping 对象。每一个标签都会被解析成 MappedStatement 对象,该标签内的 sql 会被解析成 BoundSql 对象。

为什么说 Mybatis 是半自动的 ORM 映射工具呢?它与全自动的 ORM 映射工具在哪些方面存在区别呢?

Hibernate 是全自动的 ORM 映射工具。使用 Hibernate 进行查询关联对象或关联集合对象时,能够依据对象关系模型直接获取。而 Mybatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以它被称为半自动 ORM 映射工具。

该内容来源于 my.oschina.net 上 zudajun 的博客,博客编号为 747682。

最近三期

与其在网上拼命找题?不如马上关注我们~

温馨提示:本内容地址http://m.ysjob.cc/article/articledetail-223179.html转载请注明,以上Java面试题精选:深入理解#{}和${}的区别与用法资讯信息来自颍上人才网(颍上地区最大的颍上人才网颍上人才网

 
 ©2003-2018 颍上人才网  
客服电话:  QQ: