每日三个JAVA经典面试题(二十七)

1.Mybatis中如何指定使用哪一种Executor执行器?

在MyBatis中,可以通过在MyBatis的全局配置文件(mybatis-config.xml)中配置executorType属性来指定使用哪种Executor执行器。具体做法是在settings元素下设置executorType属性,例如:

xml 复制代码
<configuration>
  <settings>
    <!-- 指定执行器类型 -->
    <setting name="executorType" value="REUSE"/>
    
    <!-- 可选值:SIMPLE(默认), REUSE, BATCH -->
  </settings>

  <!-- 其他配置项... -->

</configuration>

这里,可选的executorType值包括:

  • SIMPLE: 简单执行器,默认选项,每次执行都会创建一个新的PreparedStatement。
  • REUSE: 可重用执行器,尝试重用预编译的PreparedStatement,但需要注意的是,MyBatis 3.x之后已经废弃了这个执行器。
  • BATCH: 批处理执行器,用于批量执行SQL,可以大幅提高批量插入、更新和删除操作的性能。

如果你想要在某个特定的Mapper接口或者方法级别上覆盖全局配置,可以通过在对应的mapper映射文件中的<select>, <insert>, <update>, <delete>标签上设置executorType属性来实现局部覆盖。不过要注意的是,mapper级别的executorType设置并不支持REUSE,只支持SIMPLEBATCH

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

是的,MyBatis 支持延迟加载(也称为懒加载)。延迟加载是一种优化技术,它允许在实际需要数据时才进行查询,而不是在创建对象时就加载所有可能用到的数据。这种方式可以显著提高应用程序的性能,尤其是在处理具有复杂关联关系的数据模型时。

延迟加载的配置

在 MyBatis 中启用延迟加载,需要在配置文件 mybatis-config.xml 中进行设置:

xml 复制代码
<settings>
    <!-- 开启延迟加载的总开关 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 将积极加载改为按需加载(即对象被调用时才加载) -->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>
  • lazyLoadingEnabled: 控制是否启用延迟加载,默认为 false。设置为 true 后,MyBatis 会延迟加载所有关联对象。
  • aggressiveLazyLoading: 控制加载行为,默认为 true。当设置为 false 时,对象只有在访问其关联的对象时才加载它们,而不是在加载任何属性时就加载所有关联对象。

实现原理

MyBatis 实现延迟加载的原理主要依赖于代理对象。当配置了延迟加载时,MyBatis 会为那些配置了延迟加载的关联对象创建一个代理(Proxy)。这个代理对象在外部代码首次访问它的方法时,才会触发真正的数据库查询操作。

  1. 代理对象:MyBatis 使用 CGLIB 或 JDK 动态代理(取决于对象类型是接口还是类)来创建关联对象的代理。
  2. 触发加载:当程序访问代理对象的任何方法时,代理逻辑会判断该关联对象是否已经被加载。如果还没有加载,代理就会执行实际的 SQL 查询来加载数据,并将结果设置到代理对象中。
  3. 透明访问:一旦数据被加载,代理对象就会把对它的方法调用委托给实际加载的数据对象,之后的访问就如同直接使用数据对象一样,对使用者来说是透明的。

这种延迟加载的策略允许减少初始化对象时的数据库访问量,特别是对于那些不一定需要立即使用所有数据的场景,可以有效减少资源的消耗,提高应用性能。然而,使用延迟加载时也需要注意,它可能导致 N+1 查询问题,即访问每个对象的关联数据时都要执行一次数据库查询。因此,在设计延迟加载策略时,需要仔细考虑其对性能的潜在影响。

3.#{}和${}的区别

在MyBatis框架中,#{}${}都是用来处理动态SQL参数的占位符,它们有明显的区别:

  1. #{}

    • 预编译处理#{}符号用于预编译参数标记,MyBatis会将#{}替换成 PreparedStatement 中的占位符?,并在执行SQL时通过PreparedStatement接口的setXXX方法来设置参数值。
    • 安全性:由于采用了预编译机制,MyBatis能够自动对传入的参数进行适当地转义处理,从而有效地防止SQL注入攻击。
    • 类型安全:MyBatis可以根据参数类型自动转换并正确处理,例如对于日期、数字类型的参数无需手动添加引号。
  2. ${}

    • 字符串替换${}符号则表示字符串替换,MyBatis会直接将${}内的变量内容原样替换到SQL语句中,不做任何转义或类型处理。
    • 安全性较低 :因为没有预编译和转义处理,如果用户提供的数据未经充分验证或过滤,使用${}可能导致SQL注入风险。
    • 适用场景${}通常用于那些确实需要原样输出到SQL语句中的情况,例如动态构造表名或列名,但在这种情况下,开发者需要自行确保这些动态部分的安全性。

综上所述,一般建议尽可能使用#{}来处理动态参数,因为它更安全、更易于处理不同类型的数据,并且有助于提高SQL执行效率(由于预编译SQL语句仅需编译一次,后续只需替换参数即可执行)。而${}应当谨慎使用,并仅限于确实需要直接插入SQL文本而不涉及用户输入或者不受信任数据的情况下。

相关推荐
喝旺仔la3 分钟前
VSCode的使用
java·开发语言·javascript
qing_04060313 分钟前
C++——模板初阶
开发语言·c++·模板
YOLO数据集工作室24 分钟前
Python介绍
开发语言·python
青年有志24 分钟前
Web 服务器介绍 | 通过 Tomcat 说明其作用
服务器·前端·tomcat
多思考少编码26 分钟前
【LGR-200-Div.4】洛谷入门赛 #27 A - H题解,包含(C++, Go语言)
开发语言·c++·golang·洛谷·算法竞赛
骆晨学长26 分钟前
基于Springboot的助学金管理系统设计与实现
java·spring boot·后端
尘浮生31 分钟前
Java项目实战II基于Java+Spring Boot+MySQL的大型商场应急预案管理系统(源码+数据库+文档)
java·开发语言·数据库·spring boot·spring·maven·intellij-idea
一水鉴天38 分钟前
智能工厂的软件设计 “程序program”表达式,即 接口模型的代理模式表达式
开发语言·人工智能·中间件·代理模式
蒙娜丽宁43 分钟前
深入理解Go语言中的接口定义与使用
开发语言·后端·golang·go
dawn19122844 分钟前
SpringMVC 中的域对象共享数据
java·前端·servlet