如果有遗漏,评论区告诉我进行补充
面试官: mybatis是否支持延迟加载?延迟加载的原理是什么?
我回答:
一、MyBatis是否支持延迟加载?
MyBatis支持延迟加载(Lazy Loading)。延迟加载是一种数据加载策略,它允许在真正需要访问某个对象的关联数据时,才从数据库中加载这些数据,而不是在查询主对象时立即加载所有关联的数据。这种机制有助于提高性能和减少资源消耗。
Mybatis延迟加载的支持
在 MyBatis 中,可以通过配置 <association>
和 <collection>
标签的 fetchType
属性来控制是否启用延迟加载:
- lazy:表示使用延迟加载。
- eager:表示立即加载,默认值。
例如,在配置文件中定义一个关联映射时可以这样设置:
<resultMap id="userResultMap" type="User"><id property="id" column="user_id"/><result property="name" column="user_name"/><!-- 使用 lazy 来指定延迟加载 --><association property="department" column="dept_id" javaType="Department" fetchType="lazy"><id property="id" column="dept_id"/><result property="name" column="dept_name"/></association>
</resultMap>
在这个例子中,当从数据库获取 User 对象时,并不会立即查询相关的 Department 信息;只有当你第一次访问 User 的 department 属性时,才会触发对 Department 的查询。
二、结合Spring框架层面的延迟加载原理
工作流程如下:
- 初始化阶段:在初始化阶段,MyBatis 创建实体对象时,对于设置了延迟加载的属性,并不直接加载对应的关联数据,而是创建一个代理对象放在该属性位置上。
- 属性访问:当程序尝试访问设置了延迟加载的属性时,实际上是访问到了代理对象。此时,代理对象会检测到实际的数据尚未被加载。
- 触发加载:代理对象会自动执行预设的 SQL 语句去数据库中查询对应的数据,并将查询结果填充到代理对象内部的真实对象中。
- 返回结果:最后,代理对象将已经加载好的真实对象返回给调用者。
-
配置开启:
- 在MyBatis的配置文件中(通常是
mybatis-config.xml
),通过配置<setting name="lazyLoadingEnabled" value="true"/>
来开启全局延迟加载。 - 在Mapper映射文件中,也可以针对具体的关联关系设置
fetchType="lazy"
,以实现更细粒度的延迟加载控制。
- 在MyBatis的配置文件中(通常是
-
代理对象:
- 当主对象(如用户)被查询时,MyBatis不会立即加载其关联对象(如订单)的数据。相反,MyBatis会为关联对象创建一个代理对象,该代理对象持有对真实数据的引用或查询数据的能力。
- 这个代理对象在内存中占用较小,且不会立即执行数据库查询。
-
按需加载:
- 当访问代理对象的某个方法或属性时(如调用
user.getOrders()
),MyBatis会检测到这是一个延迟加载的关联对象。 - 此时,MyBatis会触发延迟加载机制,执行额外的数据库查询来获取关联对象的数据。
- 查询完成后,MyBatis将查询结果填充到代理对象中,使得关联对象的数据变得可用。
- 当访问代理对象的某个方法或属性时(如调用
-
动态代理:
- MyBatis通过动态代理技术实现延迟加载。具体来说,它使用如CGLIB这样的库来创建目标对象的代理对象。
- 当调用代理对象的方法时,会进入一个拦截器(Interceptor),该拦截器会检查是否需要执行延迟加载。如果需要,则执行数据库查询并更新代理对象的状态。
-
性能考虑:
- 延迟加载有助于减少不必要的数据库查询,特别是在处理具有复杂关联关系的对象时。然而,它也可能导致“N+1查询问题”,即当需要访问多个关联对象时,可能会执行多次数据库查询,从而降低性能。
- 因此,在使用延迟加载时,需要权衡其带来的性能优势和潜在的查询开销。
三、注意事项
- 数据一致性:如果延迟加载的对象在外部环境中被修改或删除,那么在加载关联对象时可能会出现数据不一致的情况。
- 序列化问题:由于延迟加载依赖于动态代理,因此代理对象可能无法直接序列化。如果需要将包含延迟加载关联对象的数据传输到远程系统或进行持久化存储,需要特别注意这一点。
- 配置灵活性:MyBatis提供了丰富的配置选项来支持延迟加载,包括全局配置和局部配置。开发者可以根据实际需求灵活配置延迟加载策略。
综上所述,MyBatis通过配置开启、代理对象、按需加载和动态代理等技术手段实现了延迟加载功能,为开发者提供了更细粒度的数据加载控制选项。在面试中,能够清晰阐述这些原理和注意事项将有助于展现你的技术深度和广度。