MyBatis-面试题

本文深入解析MyBatis框架的关键特性,包括#{}

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. MyBatis 中 #{}和 ${}的区别是什么?

\#{}是预编译处理,${}是字符替换。

在使用 #{}时,MyBatis 会将 SQL 中的 #{}替换成“?”,配合 PreparedStatement 的 set 方法赋值,这样可以有效的防止 SQL 注入,保证程序的运行安全。

2. MyBatis 有几种分页方式?

分页方式:逻辑分页和物理分页。

逻辑分页: 使用 MyBatis 自带的 RowBounds 进行分页,它是一次性查询很多数据,然后在数据中再进行检索。

物理分页: 自己手写 SQL 分页或使用分页插件 PageHelper,去数据库查询指定条数的分页数据的形式。

3. RowBounds 是一次性查询全部结果吗?为什么?

RowBounds 表面是在“所有”数据中检索数据,其实并非是一次性查询出所有数据,因为 MyBatis 是对 jdbc 的封装,在 jdbc 驱动中有一个 Fetch Size 的配置,它规定了每次最多从数据库查询多少条数据,假如你要查询更多数据,它会在你执行 next()的时候,去查询更多的数据。就好比你去自动取款机取 10000 元,但取款机每次最多能取 2500 元,所以你要取 4 次才能把钱取完。只是对于 jdbc 来说,当你调用 next()的时候会自动帮你完成查询工作。这样做的好处可以有效的防止内存溢出。

4. MyBatis 逻辑分页和物理分页的区别是什么?

  • 逻辑分页是一次性查询很多数据,然后再在结果中检索分页的数据。这样做弊端是需要消耗大量的内存、有内存溢出的风险、对数据库压力较大。
  • 物理分页是从数据库查询指定条数的数据,弥补了一次性全部查出的所有数据的种种缺点,比如需要大量的内存,对数据库查询压力较大等问题。

5. MyBatis 是否支持延迟加载?延迟加载的原理是什么?

MyBatis 支持延迟加载,设置 lazyLoadingEnabled=true 即可。

延迟加载的原理的是调用的时候触发加载,而不是在初始化的时候就加载信息。比如调用 a. getB(). getName(),这个时候发现 a. getB() 的值为 null,此时会单独触发事先保存好的关联 B 对象的 SQL,先查询出来 B,然后再调用 a. setB(b),而这时候再调用 a. getB(). getName() 就有值了,这就是延迟加载的基本原理。

6. 说一下 MyBatis 的一级缓存和二级缓存?

  • 一级缓存:基于 PerpetualCache 的 HashMap 本地缓存,它的声明周期是和 SQLSession 一致的,有多个 SQLSession 或者分布式的环境中数据库操作,可能会出现脏数据。当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认一级缓存是开启的。
  • 二级缓存:也是基于 PerpetualCache 的 HashMap 本地缓存,不同在于其存储作用域为 Mapper 级别的,如果多个SQLSession之间需要共享缓存,则需要使用到二级缓存,并且二级缓存可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现 Serializable 序列化接口(可用来保存对象的状态)。

开启二级缓存数据查询流程:二级缓存 -> 一级缓存 -> 数据库。

缓存更新机制:当某一个作用域(一级缓存 Session/二级缓存 Mapper)进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。

7. MyBatis 和 hibernate 的区别有哪些?

  • 灵活性:MyBatis 更加灵活,自己可以写 SQL 语句,使用起来比较方便。
  • 可移植性:MyBatis 有很多自己写的 SQL,因为每个数据库的 SQL 可以不相同,所以可移植性比较差。
  • 学习和使用门槛:MyBatis 入门比较简单,使用门槛也更低。
  • 二级缓存:hibernate 拥有更好的二级缓存,它的二级缓存可以自行更换为第三方的二级缓存。
# Spring Boot 集成 MyBatis, 分页插件 PageHelper, 通用 Mapper ## 项目依赖 ```xml <!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> <!--mapper--> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> <!--pagehelper--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> ``` ## Spring DevTools 配置 在使用 DevTools 时,通用Mapper经常会出现 class x.x.A cannot be cast to x.x.A。 同一个类如果使用了不同的类加载器,就会产生这样的错误,所以解决方案就是让通用Mapper和实体类使用相同的类加载器即可。 DevTools 默认会对 IDE 中引入的所有项目使用 restart 类加载器,对于引入的 jar 包使用 base 类加载器,因此只要保证通用Mapper的jar包使用 restart 类加载器即可。 在 `src/main/resources` 中创建 META-INF 目录,在此目录下添加 spring-devtools.properties 配置,内容如下: ```properties restart.include.mapper=/mapper-[\\w-\\.]+jar restart.include.pagehelper=/pagehelper-[\\w-\\.]+jar ``` 使用这个配置后,就会使用 restart 类加载加载 include 进去的 jar 包。 ## 集成 MyBatis Generator 通过 Maven 插件集成的,所以运行插件使用下面的命令: >mvn mybatis-generator:generate Mybatis Geneator 详解: >http://blog.youkuaiyun.com/isea533/article/details/42102297 ## application.properties 配置 ```properties #mybatis mybatis.type-aliases-package=tk.mybatis.springboot.model mybatis.mapper-locations=classpath:mapper/*.xml #mapper #mappers 多个接口时逗号隔开 mapper.mappers=tk.mybatis.springboot.util.MyMapper mapper.not-empty=false mapper.identity=MYSQL #pagehelper pagehelper.helperDialect=mysql pagehelper.reasonable=true pagehelper.supportMethodsArguments=true pagehelper.params=count=countSql ``` ## application.yml 配置 完整配置可以参考 [src/main/resources/application-old.yml](https://github.com/abel533/MyBatis-Spring-Boot/blob/master/src/main/resources/application-old.yml) ,和 MyBatis 相关的部分配置如下: ```yaml mybatis: type-aliases-package: tk.mybatis.springboot.model mapper-locations: classpath:mapper/*.xml mapper: mappers: - tk.mybatis.springboot.util.MyMapper not-empty: false identity: MYSQL pagehelper: helperDialect: mysql reasonable: true supportMethodsArguments: true params: count=countSql ``` 注意 mapper 配置,因为参数名固定,所以接收参数使用的对象,按照 Spring Boot 配置规则,大写字母都变了带横线的小写字母。针对如 IDENTITY(对应i-d-e-n-t-i-t-y)提供了全小写的 identity 配置,如果 IDE 能自动提示,看自动提示即可。 ## SSM集成的基础项目 >https://github.com/abel533/Mybatis-Spring ## MyBatis工具 http://www.mybatis.tk - 推荐使用 Mybatis 通用 Mapper3 https://github.com/abel533/Mapper - 推荐使用 Mybatis 分页插件 PageHelper https://github.com/pagehelper/Mybatis-PageHelper ## 作者信息 - 作者博客:http://blog.youkuaiyun.com/isea533 - 作者邮箱:abel533@gmail.com
<think>好的,我现在需要回答用户关于MyBatis-Plus的常见面试题及答案。首先,我需要回忆一下MyBatis-Plus的相关知识,并参考用户提供的引用内容。用户给出的引用主要涉及MyBatis的基础知识、缓存机制、逻辑删除以及手写MyBatis的内容,但用户现在需要的是MyBatis-Plus的内容。因此,我需要结合自己的知识,同时利用已有的引用信息,特别是引用[5]提到的逻辑删除相关内容,来构建回答。 首先,MyBatis-Plus是MyBatis的增强工具,在MyBatis的基础上提供了更多便捷的功能,比如通用的CRUD操作、分页插件、代码生成器等。常见的面试问题可能包括以下几个方面: 1. MyBatis-Plus与MyBatis的区别和优势:需要说明MyBatis-Plus在简化开发、内置通用Mapper、分页插件等方面的改进。 2. 主键生成策略:MyBatis-Plus支持的策略如自增、UUID、雪花算法等。 3. 逻辑删除的实现:引用[5]提到了使用@TableLogic注解,可以详细说明。 4. 自动填充功能:如创建时间、更新时间自动填充。 5. 条件构造器:如何使用QueryWrapper或LambdaQueryWrapper构建查询条件。 6. 性能优化:如分页插件、SQL注入器等。 7. 与MyBatis的兼容性:是否支持共存,如何切换使用。 接下来需要确保回答的结构清晰,每个问题都有解答和示例,可能的话结合代码。例如,逻辑删除部分可以参考引用[5],提到使用@TableLogic注解以及配置步骤。同时,需要引用已有的引用内容,比如在提到一级缓存时引用[3],但需要注意MyBatis-Plus是否对缓存有扩展或修改。 需要注意的是,用户提供的引用中并没有直接提到MyBatis-Plus的内容,除了引用[5]涉及逻辑删除,但MyBatis-Plus的逻辑删除确实是通过@TableLogic实现的,所以这里可以正确引用。其他部分可能需要依赖自己的知识,但应确保准确性。 可能还需要考虑分页插件、ActiveRecord模式、代码生成器等功能的常见问题。例如,如何配置分页插件,如何使用条件构造器避免SQL注入,以及如何通过代码生成器快速生成代码。 最后,生成相关问题,这些问题应该围绕MyBatis-Plus的核心功能,如与MyBatis的区别、主键策略、逻辑删除、自动填充、条件构造器等,确保问题具有针对性,帮助用户深入理解。</think>### MyBatis-Plus 常见面试问题与解答 #### 1. **MyBatis-Plus 是什么?与 MyBatis 的主要区别是什么?** MyBatis-Plus 是 MyBatis 的增强工具,在保留 MyBatis 原生功能的基础上,提供了以下核心特性: - **通用 CRUD 操作**:内置通用 Mapper 和 Service,无需编写 XML 即可实现单表基本操作[^5]。 - **条件构造器**:通过 `QueryWrapper` 或 `LambdaQueryWrapper` 动态构建查询条件,避免 SQL 注入风险。 - **分页插件**:支持物理分页,且分页参数自动适配不同数据库。 - **代码生成器**:自动生成 Entity、Mapper、Service 等代码,提升开发效率。 **区别**:MyBatis-Plus 通过简化开发流程和提供开箱即用的功能,减少了冗余代码,而 MyBatis 需要手动实现更多基础操作。 --- #### 2. **如何实现逻辑删除?** 逻辑删除通过标记记录状态(如 `deleted` 字段)代替物理删除。MyBatis-Plus 的实现步骤如下: 1. **数据库表添加 `deleted` 字段**,默认值为 0(未删除)。 2. **实体类字段添加注解 `@TableLogic`**: ```java @TableLogic private Integer deleted; ``` 3. **配置全局逻辑删除值**(可选): ```yaml mybatis-plus: global-config: db-config: logic-delete-value: 1 # 已删除 logic-not-delete-value: 0 # 未删除 ``` 执行删除操作时,实际会更新 `deleted` 字段而非物理删除。 --- #### 3. **MyBatis-Plus 的主键生成策略有哪些?** 通过 `@TableId` 注解指定主键策略: - **`IdType.AUTO`**:数据库自增(需数据库支持)。 - **`IdType.ASSIGN_ID`**:雪花算法生成 Long 类型 ID(默认策略)。 - **`IdType.ASSIGN_UUID`**:生成 UUID 字符串。 示例: ```java @TableId(type = IdType.ASSIGN_ID) private Long id; ``` --- #### 4. **如何实现字段自动填充(如创建时间、更新时间)?** 1. **实体类字段添加 `@TableField` 注解**: ```java @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; ``` 2. **实现 `MetaObjectHandler` 接口**: ```java @Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.setFieldValByName("createTime", LocalDateTime.now(), metaObject); } @Override public void updateFill(MetaObject metaObject) { this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); } } ``` --- #### 5. **如何避免 SQL 注入风险?** MyBatis-Plus 的条件构造器(如 `QueryWrapper`)通过参数化查询防止 SQL 注入。例如: ```java QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name", "Alice").gt("age", 18); List<User> users = userMapper.selectList(wrapper); ``` 生成的 SQL 为 `WHERE name = ? AND age > ?`,参数通过占位符绑定[^3]。 --- #### 6. **如何配置分页插件?** 1. **添加分页插件配置类**: ```java @Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; } } ``` 2. **使用分页 API**: ```java Page<User> page = new Page<>(1, 10); // 当前页,每页数量 IPage<User> userPage = userMapper.selectPage(page, queryWrapper); ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值