1 session.Load懒加载
之前在介绍Hibernate几个方法的时候,已经提到了这个load方法
当我们从脱管态的对象查询的时候,返回的不是查询数据库的对象,而是返回的是一个代理对象,hibernate没有去查询数据库,并报了一个LazyInitializalationException异常
那返回代理对象到底是个什么对象呢
根据测试:
User user=(User)load(User.class);
syso(user.getClass);
打印结果为:
User$$EnhancerByCGLIB$$af1128bc
这个就是User对象的一个代理对象,名字是动态生成的,保证与User不重复
之所以没有报类型转换异常,是因为,这个类是继承至User的 这也说明为什么我们的Pojo类不能为final类,因为需要被继承
解决方式:
初始化代理对象,在叙述Session方法的时候已经提到了
Hibernate.Initialize(user);
这种解决方式仅仅在一个类 1对一的时候比较好,如果在一对多,多对一的时候,就不好解决了,会出问题
懒加载的实现是通过:asm.jar(字节码库) 和Cglib.jar(字节码解析器 依赖asm.jar)包实现。这两个包的作用能够动态的改变你装入内存的字节码。
使用限制:
所以Load要在关联的Session关闭之前,也就是关联的对象要是持久态的时候,代理对象可以访问数据库,产生 select语句
使用场景:
在session 关闭前,建立对象与对象之间的关联的时候,以前的employee.setDepart(department);会访问数据库,这时候就可以用load 懒加载,然后调用上述语句的时候,就不会去访问数据库了,主要起了一个优化的作用
这样的应用场景是比较少的。
2一对一懒加载
缺省情况下,hibernate 会对关联关系(一对一 多对一 多对多等 )使用懒加载。
应用场景:
一对一的方式,使用懒加载可能性要小,懒加载主要是提高性能,减少查询。根据数据交互是网络通信,数据较多时候,数据包比较多。
缺省下:
对主对象进行查询,不会进行懒加载,会进行关联查询(left join)
原因:因为主对象有个属性是从对象,查询主对象的时候,hibernate不知道这个对象能不能赋值为Null,所以查询的时候就会Join 从对象
对从对象的查询的时候,才会用懒加载的方式。
原因:personid 在idcard中是个外键 所以可以之后查询,可以懒加载,所以懒加载的一个条件要建立外键约束
当只查询从对象的时候,会产生一个主对象的代理,不会产生查询主对象的语句,当代码在访问主对象的时候,通过这个代理,就会产生访问主对象的代码
IdCard idcard = s.load(IdCard.class,id);
syso(idcard.getPserson());
一对一懒加载实现所要满足的条件:
1 lazy!= false; 默认= proxy; lazy :
表示什么时候查询相关联的属性
如果等于false 只访问主对象的时候,也会产生两条select语句,将从对象也从数据库中查出来
2constrained = true; 添加外键约束 表示引用主对象的id
3fetch = "select" 抓取方式 缺省的为select
通过什么方式来查询相关联的属性 还可以设置为join
设置为join的时候 查询从对象的时候,就会join出主对象,所以懒加载就失效了。
3一对多懒加载
应用场景:
当我们查询一对象的时候,没必要关联出多对象,如查询部门的时候,没必要查询出成百上千个员工的信息
这个如果用抓取的话,就会产生很多很多数据。
所以 一对多的懒加载很有必要
条件:
1 lazy= proxy
2 fetch = select
缺省就是这个满足懒加载条件的
4多对一懒加载
对于多对一,产生懒加载,意义其实也不大 缺省的也是懒加载
5 其他:
懒加载初始化异常:
在session关闭之后,访问对象就会如同一对一一样产生代理初始化异常
在session关闭之后,访问对象就会如同一对一一样产生代理初始化异常
LazyInitializationException
解决方式:初始化代理,初始化代理,说白了就是提前查询数据库