2025年mybatis常见面试题及答案_第1页
2025年mybatis常见面试题及答案_第2页
2025年mybatis常见面试题及答案_第3页
2025年mybatis常见面试题及答案_第4页
2025年mybatis常见面试题及答案_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

2025年mybatis常见面试题及答案MyBatis的核心组件有哪些?各自的作用与生命周期是什么?MyBatis核心组件分为5类,各组件职责与生命周期明确:SqlSessionFactoryBuilder:基于建造者模式解析MyBatis全局配置、映射文件元数据,构建SqlSessionFactory实例。生命周期仅为方法级,实例生成后即可回收,无需长期持有。SqlSessionFactory:作为MyBatis应用的全局核心工厂,负责创建SqlSession实例,全局唯一,生命周期与应用生命周期保持一致,应用启动时初始化,应用停止时销毁。SqlSession:是面向用户的操作入口,提供SQL执行、事务管理、Mapper获取等API,线程不安全,不可在多线程环境下共享,生命周期绑定单次请求/会话,请求结束后需调用close()方法释放资源。Mapper接口:无实现类的业务接口,方法与Mapper文件中的SQLID一一对应,底层通过JDK动态代理生成实例,生命周期与SqlSession绑定,随SqlSession销毁而回收。Mapper映射文件:存储SQL语句、参数映射、结果映射规则,应用启动时加载到内存,生命周期与应用一致。#{}和${}的核心区别是什么?适用场景有哪些?

二者底层实现与安全性差异显著:底层实现:#{}基于JDBC预编译机制,参数替换时会自动为字符串类型参数添加引号,底层调用PreparedStatement的setXXX()方法完成参数赋值;${}基于字符串直接拼接,将参数原值直接嵌入SQL语句,无预编译过程。安全性:#{}可完全避免SQL注入风险;${}存在SQL注入风险,若传入恶意参数会直接篡改SQL逻辑。适用场景:绝大多数参数传递场景优先使用#{};仅当需要动态拼接SQL结构时使用${},例如动态传入表名、列名、排序字段、SQL关键字等场景,此类场景下#{}会给结构参数添加引号导致SQL语法错误。安全优化:必须使用${}时需增加参数白名单校验,仅允许传入预设枚举值/合法范围的参数,避免注入风险。什么是MyBatis的一级缓存与二级缓存?各自的特点、失效场景与适用场景是什么?MyBatis缓存分为两层,默认仅开启一级缓存:一级缓存:作用域为SqlSession级别,同一个SqlSession内执行相同的MappedStatementID、相同参数的查询时,会直接返回缓存结果,无需访问数据库。失效场景包括:SqlSession关闭、执行任意增删改操作(无论是否影响当前缓存数据)、手动调用sqlSession.clearCache()、查询不同的MappedStatement。特点:自动开启无需配置,性能损耗极低,适合单会话内重复查询的场景。二级缓存:作用域为Mappernamespace级别,同一个namespace下的所有SqlSession共享缓存数据,默认关闭。开启方式为:全局配置中设置cacheEnabled=true,再在对应Mapper.xml中添加标签或在接口上添加@CacheNamespace注解。失效场景包括:当前namespace下执行任意增删改操作、缓存超时时间到期、内存不足自动淘汰。注意点:二级缓存存储的实体类必须实现Serializable接口,支持序列化持久化;跨namespace的增删改操作不会清空当前namespace的二级缓存,会产生脏读问题。适用场景:仅适合读多写少、数据一致性要求不高的场景,多数生产环境会使用Redis等分布式缓存替代二级缓存,避免脏读与集群下缓存不一致问题。MyBatis动态SQL的常用标签有哪些?各自的作用是什么?动态SQL基于OGNL表达式实现运行时SQL拼接,核心标签包括::用于条件判断,满足表达式时拼接对应的SQL片段,常用于多条件查询的动态拼接。//:类似Java的switch-case逻辑,仅匹配第一个满足条件的when分支,所有when都不满足时拼接otherwise的片段,适合多条件互斥的场景。:用于处理SQL片段的前后缀,可自动移除多余的前缀/后缀,例如移除开头多余的AND/OR、结尾多余的逗号;、是trim的封装实现,自动添加WHERE关键字并移除开头多余的AND/OR,自动添加SET关键字并移除结尾多余的逗号,分别用于条件查询与更新操作的SQL拼接。:用于遍历集合参数,支持批量插入、IN查询等场景,可配置集合名、元素别名、分隔符、前后缀等属性。:将OGNL表达式的计算结果绑定到自定义变量,可消除不同数据库的语法差异,例如模糊查询时用bind(“pattern”,“concat(‘%’,#{name},‘%’)”),无需针对MySQL、Oracle分别写拼接逻辑。MyBatis的分页实现方式有哪些?PageHelper分页插件的原理与使用注意事项是什么?MyBatis分页分为三类实现:内存分页:查询全量数据后在内存中截取对应范围的List,实现简单但性能极差,仅适合数据量小于100条的场景,大数据量下会导致OOM。原生SQL分页:针对不同数据库手动编写分页语法,例如MySQL的LIMIT、Oracle的ROWNUM、PostgreSQL的LIMIT/OFFSET,无需额外依赖但兼容性差,切换数据库需修改SQL。插件分页:基于MyBatis拦截器实现自动分页,常用组件为PageHelper与MyBatis-Plus自带的分页插件。PageHelper的核心原理:实现MyBatis的Interceptor接口,拦截Executor的query()方法,在SQL执行前首先根据分页参数生成并执行count查询获取总条数,再根据数据库类型自动拼接分页语法,最终返回封装了分页信息的Page对象。使用注意事项:分页设置PageHelper.startPage(pageNum,pageSize)必须紧跟在分页查询方法之前,中间不能插入其他查询逻辑,否则会导致分页参数绑定到其他SQL上出现分页失效;高版本PageHelper支持多数据源自动识别数据库类型,无需手动指定方言。MyBatis实现批量操作的方式有哪些?性能对比与适用场景是什么?批量操作主要有三种实现,性能从低到高:循环单条操作:遍历集合循环调用单条插入/更新方法,每次操作都要创建、销毁Statement,性能最差,仅适合数据量小于10条的场景。拼接SQL:将多条操作的参数通过拼接成一条SQL,例如insertintot(a,b)values(?,?),(?,?),仅执行一次数据库请求,性能中等;需注意MySQL下SQL长度不能超过max_allowed_packet(默认4M),数据量过大时会导致SQL过长报错,适合单次批量数据量在100-1000条的场景。BatchExecutor批量模式:通过sqlSessionFactory.openSession(ExecutorType.BATCH)获取批量模式的SqlSession,底层基于JDBC的addBatch()、executeBatch()方法,将多条SQL攒到缓冲区后一次性发送给数据库执行,性能最高,支持十万级以上的批量操作;使用时需手动调用sqlSession.flushStatements()或commit()才会真正执行SQL,避免数据未提交的问题。MyBatis-Plus自带的saveBatch()方法底层就是基于BatchExecutor实现。MyBatis如何处理多表关联映射?N+1问题的产生原因与解决方案是什么?多表关联映射通过resultMap的两个标签实现::用于多对一、一对一映射,将关联查询的结果映射为单个实体对象,例如查询订单时关联下单用户对象。:用于一对多映射,将关联查询的结果映射为实体集合,例如查询用户时关联其所有订单列表。关联查询分为两种实现,其中嵌套查询会产生N+1问题:嵌套查询:分两次执行SQL,先查询主表数据,再根据外键关联查询从表数据,若主表返回N条数据,则需要执行1次主表查询+N次从表查询,共N+1次请求,性能极差。N+1解决方案:①使用嵌套结果映射:通过JOIN连表一次性查询所有数据,MyBatis根据resultMap的主键配置自动映射为嵌套对象,仅执行1次SQL,性能最优,注意连表查询时需给不同表的同名字段设置别名,避免主键重复导致的映射错误;②开启延迟加载:全局配置lazyLoadingEnabled=true、aggressiveLazyLoading=false,仅当调用关联对象的get方法时才触发从表查询,未用到关联对象时无需额外查询,适合关联对象非必须返回的场景;③业务层直接做两次单表查询,手动组装结果,避免关联查询的性能损耗。MyBatis的插件原理是什么?如何自定义插件?MyBatis插件基于JDK动态代理+责任链模式实现,允许拦截四大核心对象的指定方法:可拦截的四大对象:Executor(执行器,拦截增删改查、事务提交/回滚操作)、StatementHandler(SQL构建器,拦截SQL拼接、参数设置)、ParameterHandler(参数处理器,拦截参数赋值)、ResultSetHandler(结果处理器,拦截结果集映射)。插件执行逻辑:每个插件都会为目标对象生成动态代理,多个插件会形成层层代理的责任链,方法调用时按配置的顺序依次执行拦截逻辑,最终调用目标方法。自定义插件的步骤:①实现Interceptor接口,重写intercept()方法编写核心拦截逻辑,重写plugin()方法生成代理对象(通用实现为returnPlugin.wrap(target,this)),重写setProperties()方法接收配置参数;②在类上添加@Intercepts注解,指定要拦截的对象、方法名、参数列表,例如@Intercepts({@Signature(type=Executor.class,method=“query”,args={MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class})});③在MyBatis全局配置中注册插件,或SpringBoot项目中直接将插件实例注入IOC容器即可生效。注意事项:拦截方法越少性能损耗越低,多个插件通过@Order注解指定执行顺序,值越小优先级越高。MyBatis的Executor执行器有哪几种?区别是什么?MyBatis有三种基础执行器,开启二级缓存时会用CachingExecutor对基础执行器做装饰:SimpleExecutor:默认执行器,每次执行SQL都会创建新的Statement对象,执行完成后立即关闭,性能一般,适合少量请求的场景。ReuseExecutor:可重用执行器,缓存Statement对象,相同SQL的重复执行会复用同一个Statement,避免重复创建的开销,性能优于SimpleExecutor,适合多重复查询的场景。BatchExecutor:批量执行器,将多条SQL攒到缓冲区,调用flush或commit时一次性发送给数据库执行,批量操作性能最高,适合大数据量的批量插入、更新场景。MyBatis3.5.x版本新增了哪些核心特性?(2025年高频新特性考点)MyBatis3.5.x是当前主流生产版本,适配JDK8+与云原生场景,核心特性包括:原生支持JDK8+的时间API(LocalDate、LocalDateTime、LocalTime),无需额外配置自定义类型处理器。支持Mapper方法返回Optional类型,自动处理空结果,避免空指针异常。优化标签的批量拼接性能,支持千级以上参数的批量操作无性能损耗。支持JDK8+的-parameters编译参数,Mapper方法多参数时无需添加@Param注解即可直接通过参数名获取值。日志适配优化,原生支持SLF4J2、Log4j2等新版日志框架,日志输出粒度更细,方便排查SQL问题。二级缓存优化,细化锁粒度,减少并发场景下的脏读概率。支持流式查询,返回Cursor对象,边查询边处理结果,避免一次性加载全量数据导致的OOM,适合百万级以上大数据量查询场景。适配GraalVM原生镜像,3.5.10及以上版本支持SpringBoot3的原生编译,云原生场景下启动速度提升10倍以上,需注意将Mapper接口、实体类添加@RegisterReflectionForBinding注解注册反射元数据,同时在原生镜像配置中指定Mapper.xml的资源路径。MyBatis与SpringBoot整合的常见配置与坑点有哪些?常用核心配置:mybatis.mapper-locations:指定Mapper.xml文件的资源路径,例如classpath:mapper/*.xml。mybatis.type-aliases-package:指定实体类的包路径,自动为实体类注册别名,Mapper文件中无需写全类名。mybatis.configuration.map-underscore-to-camel-case:开启下划线转驼峰自动映射,数据库下划线字段自动映射到Java驼峰属性。mybatis.configuration.cache-enabled:全局关闭二级缓存,生产环境一般关闭。常见坑点:Mapper接口未添加@Mapper注解,或启动类未添加@MapperScan扫描Mapper包,导致Mapper注入失败。Mapper.xml的namespace与Mapper接口的全类名不一致,或SQLID与接口方法名不一致,导致绑定异常。多参数传递时未添加@Param注解,且未开启-parameters编译参数,导致参数找不到报错。用Map接收返回结果时,下划线转驼峰不生效,因为Map的key默认是数据库字段名,需自定义结果处理器实现转换。批量插入时数据量过大,超过MySQL的max_allowed_packet限制,报错Packetforqueryistoolarge。MyBatis性能优化的常用手段有哪些?优化可从SQL、配置、操作三个层面入手:SQL层面:避免写SELECT*,仅查询需要的字段;合理添加索引,避免全表扫描;关联查询不超过3张表,超过的话建议拆分单表查询手动组装;分页查询偏移量过大时,优化为ID范围查询,例如将LIMIT100000,10优化为WHEREid>100000LIMIT10,避免全表扫描。配置层面:开启下划线转驼峰,避免冗余的resultMap配置;开启延迟加载,减少不必要的关联查询;使用高性能连接池(如HikariCP),设置合理的连接数参数,避免连接耗尽。操作层面:批量操作优先使用BatchExecutor,避免循环单条操作;大数据量查询使用流式查询,避免OOM;读多写少场景使用Redis分布式缓存,避免频繁访问数据库;减少不必要的插件使用,降低代理性能损耗。MyBatis如何处理枚举类型映射?MyBatis提供三种枚举映射方案,可根据

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论