可以看出,如果查询结果对象中有一个属性是需要延迟加载的,那整个结果对象就被替换为一个代理对象,后面对这个对象的访问,都是通过代理对象去访问的,那是否有更好的方法呢?
答案是有的,具体如下:
Student对象关联Teacher对象,需要对Teacher对象延迟加载。
一种方式就是mybatis当前的这种做法,对Student进行代理,当访问到getTeacher时就进行延迟加载,设置其teacher对象;
还有一种方式就是对teacher对象进行代理,当第一次加载之后,就将Student对象关联的teacher对象替换为真实的对象,而不再使用代理对象,这样后面对Student及Teacher的访问,就都是访问的实际对象,而不是代理对象了。
修改之后的代码:http://download.csdn.net/detail/u014569459/7372195
关键修改点说明(基于mybatis 3.2.7 版本修改):
1.修改org\apache\ibatis\executor\resultset\DefaultResultSetHandler.java类,注销掉里面生成代理对象的代码
private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
final List> constructorArgTypes = new ArrayList>();
final List
2.修改org\apache\ibatis\executor\loader\cglib\CglibProxyFactory.java类
1)在createProxy方法增加两个参数Object parentObj,String fieldNameInParent,用于访问父对象。
public Object createProxy(Object parentObj,String fieldNameInParent,Object target, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List> constructorArgTypes, List constructorArgs) {
return EnhancedResultObjectProxyImpl.createProxy(parentObj,fieldNameInParent,target, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
}
2)在EnhancedResultObjectProxyImpl类中,增加parentObj和属性,并修改默认构造函数。
private Object parentObj;
private String fieldNameInParent;
private EnhancedResultObjectProxyImpl(Object parentObj,String fieldNameInParent,Class> type, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List> constructorArgTypes, List constructorArgs) {
this.type = type;
this.lazyLoader = lazyLoader;
this.aggressive = configuration.isAggressiveLazyLoading();
this.lazyLoadTriggerMethods = configuration.getLazyLoadTriggerMethods();
this.objectFactory = objectFactory;
this.constructorArgTypes = constructorArgTypes;
this.constructorArgs = constructorArgs;
this.parentObj = parentObj;
this.fieldNameInParent = fieldNameInParent;
}
3)修改intercept函数
if(parentObj!=null)
{
Field field = parentObj.getClass().getDeclaredField(fieldNameInParent);
Object obj = field.get(parentObj);
return method.invoke(obj, args);
}
else
{
return methodProxy.invokeSuper(enhanced, args);
}
修改文件列表(共4个):
完整代码链接:https://code.csdn.net/snippets/355671
1.CglibProxyFactory.java
2.JavassistProxyFactory.java
3.ProxyFactory.java
4.DefaultResultSetHandler.java