Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association 指的就是一对一,collection 指的就是一对多查询。在 Mybatis配置文件中,可以配置是否启用延迟加载 lazyLoadingEnabled=true|false。它的原理是,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器 invoke()方法发现 a.getB()是null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用 a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。当然了,不光是 Mybatis,几乎所有的包括 Hibernate,支持延迟加载的原理都是一样的。
1条回答 默认 最新
关注 题主你好,关于 MyBatis 创建代理对象用于延迟加载的实现,默认情况下并非使用 cglib 实现,而是使用 javassist,如果需要调整为 cglib 可以在配置中的 proxyFactory 进行设置,可以指定为 CGLIB 或 JAVASSIST,官网相关配置说明见 mybatis 配置。
另外从源码中也可以验证官网的说明。源码中用于创建代理对象的代码如下:
public class DefaultResultSetHandler implements ResultSetHandler { /** * 创建返回结果 * * @param rsw 结果集 * @param resultMap 结果映射 * @param lazyLoader 结果的属性加载器 Map * @param columnPrefix 列前缀 * @return * @throws SQLException */ private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException { this.useConstructorMappings = false; // reset previous mapping result final List<Class<?>> constructorArgTypes = new ArrayList<>(); final List<Object> constructorArgs = new ArrayList<>(); Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix); if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) { final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings(); for (ResultMapping propertyMapping : propertyMappings) { // issue gcode #109 && issue #149 if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) { // 创建懒加载的代理,用于懒加载属性 resultObject = configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs); break; } } } this.useConstructorMappings = resultObject != null && !constructorArgTypes.isEmpty(); // set current mapping result return resultObject; } }
这里的代理工厂 ProxyFactory 从配置 Configuration 中读取,Configuration 涉及 ProxyFactory 的代码如下。
public class Configuration { protected ProxyFactory proxyFactory = new JavassistProxyFactory(); // #224 Using internal Javassist instead of OGNL public ProxyFactory getProxyFactory() { return proxyFactory; } public void setProxyFactory(ProxyFactory proxyFactory) { if (proxyFactory == null) { proxyFactory = new JavassistProxyFactory(); } this.proxyFactory = proxyFactory; } }
从配置 Configuration 中可以看出,默认的 ProxyFactory 是 JavassistProxyFactory。
如果需要调整,对于纯 mybatis 项目,可以在 xml 配置文件中指定。
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties> <!--<property name="proxyFactory" value="JAVASSIST"/>--> <property name="proxyFactory" value="CGLIB"/> </properties> </configuration>
mybatis 解析 proxyFactory 配置的代码如下。
public class XMLConfigBuilder extends BaseBuilder { private void settingsElement(Properties props) { ... 省略部分代码 configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory"))); ... 省略部分代码 } }
对于技术的探索,最好还是持有怀疑态度,不要人云亦云。如果题主对自问自答这种形式感兴趣不妨写几篇博客。了解 mybatis 其他内容,还可以参阅我写的几篇关于 mybatis 的文章,专栏为 MyBatis 源码之旅。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报
悬赏问题
- ¥15 乌班图ip地址配置及远程SSH
- ¥15 怎么让点阵屏显示静态爱心,用keiluVision5写出让点阵屏显示静态爱心的代码,越快越好
- ¥15 PSPICE制作一个加法器
- ¥15 javaweb项目无法正常跳转
- ¥15 VMBox虚拟机无法访问
- ¥15 skd显示找不到头文件
- ¥15 机器视觉中图片中长度与真实长度的关系
- ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
- ¥15 R语言卸载之后无法重装,显示电脑存在下载某些较大二进制文件行为,怎么办
- ¥15 java 的protected权限 ,问题在注释里