记得刚进项目组的时候leader给我介绍过NotFound(action=NotFoundAction.IGNORE)会导致Fetch无效,这样的话无论你设置fetchType是lazy还是eager都会以eager加载,一开始我开始模糊的记住,但是过不了2天就会忘,今天有个任务也是配Ignore的,索性就看看里面到底是怎么整的,下面把发现的贴出来:
先看org.hibernate.type.ManyToOneType
public class ManyToOneType extends EntityType {
private final boolean ignoreNotFound;
public ManyToOneType(String className) {
this( className, false );
}
public ManyToOneType(String className, boolean lazy) {
super( className, null, !lazy, true, false );
this.ignoreNotFound = false;
}
这里可以清楚的看到对ManyToOneType来说 默认的是eager加载(前两个红色标注),ignoreNotFound是false,也就是说默认的NotFound不是ignore,即是Exception。
好的,接着往下看org.hibernate.impl.SessionImpl的internalLoad方法:
public Object internalLoad(String entityName, Serializable id, boolean eager, boolean nullable) throws HibernateException {
// todo : remove
LoadEventListener.LoadType type = nullable ?
LoadEventListener.INTERNAL_LOAD_NULLABLE :
eager ? LoadEventListener.INTERNAL_LOAD_EAGER : LoadEventListener.INTERNAL_LOAD_LAZY;
LoadEvent event = new LoadEvent(id, entityName, true, this);
fireLoad(event, type);
if ( !nullable ) {
UnresolvableObjectException.throwIfNull( event.getResult(), id, entityName );
}
return event.getResult();
}
这里假设你ManyToOne上设置的是NotFoundAction.IGNORE,ignoreNotFound这个属性就会设置为true,掉这个方法时传进来的boolean nullable就是true,这是大前提。
看红色字体的三目运算符,a?b:c,计算规则,先计算a,a为true的话计算b的值返回,a为false计算c的值返回。对a?b:c?d:e这个有点复杂,可以这样换算a?b(c?d:e).也就是说a为false的话计算c?d:e的值返回。
由于nullable是true,咱们就看INTERNAL_LOAD_NULLABLE 这几个常量的值。
下面看org.hibernate.event.LoadEventListener:
public static final LoadType INTERNAL_LOAD_EAGER = new LoadType("INTERNAL_LOAD_EAGER")
.setAllowNulls(false)
.setAllowProxyCreation(false)
.setCheckDeleted(false)
.setNakedEntityReturned(false);
public static final LoadType INTERNAL_LOAD_LAZY = new LoadType("INTERNAL_LOAD_LAZY")
.setAllowNulls(false)
.setAllowProxyCreation(true)
.setCheckDeleted(false)
.setNakedEntityReturned(false);
public static final LoadType INTERNAL_LOAD_NULLABLE = new LoadType("INTERNAL_LOAD_NULLABLE")
.setAllowNulls(true)
.setAllowProxyCreation(false)
.setCheckDeleted(false)
.setNakedEntityReturned(false);
这里看到 .setAllowProxyCreation(false) 也就是代理创建false,这样话就不是懒加载!!!看到设置为lazy的是.setAllowProxyCreation(true),设置为eager的是.setAllowProxyCreation(false),基本能说明eager不创建代理,lazy是代理加载
最后再贴段代码证明哪里调用这布尔值:
org.hibernate.event.def.DefaultLoadEventListener
的proxyOrLoad方法:
if ( options.isAllowProxyCreation() ) {
return createProxyIfNecessary( event, persister, keyToLoad, options, persistenceContext );
}
else {
// return a newly loaded object
return load(event, persister, keyToLoad, options);
}
}
看hibernate上的注解写的很清楚,如果AllowProxyCreation这布尔值为false的话会返回一个新的加载对象!
从上面的代码不难从hibernate框架的代码中看出hibernate的一些默认设置方式。这里还多亏maven的应用,要是以前不用maven,想一窥ssh的源码还要自己下载,自己加载进去,效率低而繁琐,万一换个workspase就得重新来一遍。
一天进步一点点。