"MyBatis最新2023年面试题,高级面试题及附答案解析"
### MyBatis缓存机制
MyBatis提供了一级缓存和二级缓存两个级别的缓存机制,以提高数据库操作的性能。
1. **一级缓存**:一级缓存是基于PerpetualCache实现的HashMap,它的工作范围是Session。当在一个Session中执行SQL并获取结果后,这些结果会存储在一级缓存中。如果后续在同一Session中再次执行相同的SQL,MyBatis会首先检查一级缓存,避免重复执行SQL。但是,当Session flush或close后,一级缓存将被清空。
2. **二级缓存**:二级缓存的作用范围更大,是基于Mapper(Namespace)的。与一级缓存类似,二级缓存也使用HashMap存储数据,但它是跨Session共享的。二级缓存默认是关闭的,需要在对应的Mapper配置文件中启用`<cache/>`标签,并确保返回的对象实现`Serializable`接口以支持序列化,这是跨Session传递数据的必要条件。二级缓存的更新机制与一级缓存相同,即当进行C/U/D操作后,相关Namespace下的所有缓存会被清除。
### Mybatis的Xml映射文件与内部数据结构映射关系
Mybatis的核心组件是Configuration对象,它包含了所有XML配置信息。以下是如何将XML映射文件解析到内部数据结构:
1. `parameterMap`标签被解析为`ParameterMap`对象,其中的子元素转化为`ParameterMapping`对象,用于描述参数映射。
2. `resultMap`标签被解析为`ResultMap`对象,其子元素转化为`ResultMapping`对象,用于处理结果集的映射。
3. 每个`<select>`, `<insert>`, `<update>`, `<delete>`标签都会解析成一个`MappedStatement`对象,其中的SQL语句被解析为`BoundSql`对象,记录了动态SQL的信息。
### 延迟加载(Lazy Loading)
Mybatis支持关联对象(association)和关联集合(collection)的延迟加载,以提高性能。例如,一对一(association)和一对多(collection)查询。延迟加载是指在真正需要数据时才进行加载,而不是在查询时立即加载所有关联数据。
**实现原理**:
Mybatis通过CGLIB库动态生成目标对象的代理对象。当尝试访问被延迟加载的属性时,代理对象会检查是否已经加载了关联数据。如果没有,它会在后台执行相应的SQL查询,并将结果设置到目标对象的属性上。这种方式减少了不必要的数据库交互,提高了应用的响应速度。
例如,如果我们有一个User对象和对应的Address对象,User中有一个Address属性标记为延迟加载。在第一次访问User的Address属性时,Mybatis会触发一个额外的查询来获取Address信息,然后设置给User对象。
请注意,延迟加载需要在Mybatis的全局配置文件中启用`lazyLoadingEnabled=true`。同时,为了防止循环引用,Mybatis还提供了`aggressiveLazyLoading=false`的配置选项,以决定是否在任何属性访问时都立即加载所有延迟加载属性。