Hibernate3.6.2 懒加载分析
来源:互联网 发布:apache kylin 编辑:程序博客网 时间:2024/05/29 13:40
原文链接:http://xdwangiflytek.iteye.com/blog/1830969
懒加载是指程序推迟访问数据库,这样做可以保证有时候不必要的访问数据库,提供性能。
一、load方法的懒加载
- public class UserManager {
- public static void main(String[] args) {
- Users user = new Users();
- user.setBirthday(new Date());
- Name name = new Name();
- name.setFirstName("wang");
- name.setLastName("xudong");
- user.setName(name);
- addUser(user);
- Users users = getUser(user.getId());
- System.out.println(users.getName());
- }
- static Users getUser(int id){
- Session session = HibernateUtil.getSession();
- try {
- Users users = (Users) session.load(Users.class, id);
- return users;
- } finally{
- session.close();
- }
- }
- static void addUser(Users users){
- Session session = null;
- Transaction tx = null;
- try {
- session = HibernateUtil.getSession();
- tx = session.beginTransaction();
- session.save(users);
- tx.commit();
- } catch (HibernateException e) {
- if (tx!=null) {
- tx.rollback();
- } throw e;
- }finally{
- if(session!=null){
- session.close();
- }
- }
- }
上面代码是先增加一个用户、然后再查询这个用户的name组合属性。运行上面的时候,该程序会抛出这样一个异常:Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session这就是懒加载不能初始化异常。其原因就在于no session。在前面个持久化对象中已经说明:使用load方法时,该方法将具有延迟加载的功能,load方法并不会立即去访问数据库,它会返回一个代理对象,只有当你真正去访问这个对象的时候,它才会去访问数据库。
通过上面的图,我们看出,Hibernate根本就没有select语句,也就是说Hibernate没有去访问数据库,所以这个时候你去访问它肯定是没有的。但为什么没有抛出空指针异常?没有抛出空指针异常,也就是说明User对象是存在的,那它是什么呢?通过输出user.getClass()可以看出是这样一个东西:class com.hibernate.domain.Users_$$_javassist_5。这个user就是load返回的代理对象。但是这个对象并不是我们所要的。我们所要的是一个User实例对象。
那么怎么解决这个问题呢?
第一种方法:在关闭session之前访问该对象
- static Users getUser(int id){
- Session session = HibernateUtil.getSession();
- try {
- Users users = (Users) session.load(Users.class, id);
- users.getName();
- return users;
- } finally{
- session.close();
- }
- }
但是从规范性上看,别不符合规范,所以我们一般也可以采用
- static Users getUser(int id){
- Session session = HibernateUtil.getSession();
- try {
- Users users = (Users) session.load(Users.class, id);
- Hibernate.initialize(users);
- return users;
- } finally{
- session.close();
- }
- }
利用hibernate的initialize()方法将这个代理对象给初始化。
注:在使用代理对象的getId()方法和getClass()方法的时候,并不会抛出不能初始化异常,因为这两个属性并不用查询数据库。
二、关联关系下的懒加载
1、one-to-one懒加载
一对一的懒加载并不常用,因为懒加载的目的是为了减少与数据库的交互,从而提高执行效率,而在一对一关系中,主表中的每一条数据只对应从表的一条数据库,就算都查询也不会增加多少交互的成本,而且主表不能有contrained=true,所以主表是不能懒加载的。但是从表可以有。
实现此种懒加载必须在从对象这边同时满足三个条件:
1、lazy!=false(lazy的属性有三个选项分别为:no-proxy、false和proxy)
2、Constrained = true ;
3、fetch=select。
注:当fetch设置为join时,懒加载就会失效。因为fetch的作用是抓取方式,他有两个值分别为select和join,默认值为select。即在设为join时,他会直接将从表信息以join方式查询到而不是再次使用select查询,这样导致了懒加载的失效。
2、one-to-many懒加载
与one-to-one关联不同,对one-to-many而言,主表的每一条属性都会对应从表的多条数据,这个时候懒加载就显得非常有效了。比如一个部门里面有多个员工,如果没有懒加载,每查询这个部门的时候都会查询出多个员工,这会大大增加与数据库交互的成本。所以Hbernate默认的是加入懒加载的。这就是查询集合属性的时候返回的是一个PersistentIndexed*类型对象的原因。该对象其实就是一个代理对象。当然,可以在映射文件中通过将lazy属性设为假来禁用。
Hibernate默认对one-to-many就是使用的懒加载,但用户也可以取消懒加载操作:
一:设置lazy=”false”;
二:设置fetch=”join”.
实现此种懒加载必须在从对象这边同时满足两个条件:
1、lazy!=false(lazy的属性有三个选项分别为:no-proxy、false和proxy)
2、fetch=select。
3、many-to-one懒加载
此关联关系的懒加载和one-to-one的懒加载一样都是可要可不要的,因为对执行效率的提高都不是非常明显。虽然多对一与一对一关系方式相同,但是在Hibernate中多对一时,默认是进行懒加载的。另外有一点需要注意的是懒加载并不会区分集合属性里面是否有值,即使是没有值,他依然会使用懒加载。
实现此种懒加载必须在从对象这边同时满足两个条件
1、lazy!=false(lazy的属性有三个选项分别为:no-proxy、false和proxy)
2、fetch=select
4、many-to-many懒加载
此关联关系的懒加载和one-to-many的懒加载一样对程序的执行效率的提高都是非常明显的。
实现此种懒加载必须在从对象这边同时满足两个条件:
1、lazy!=false(lazy的属性有三个选项分别为:no-proxy、false和proxy)
2、fetch=select
能够懒加载的对象都是被改过的代理对象,当相应的对象没有关闭时,访问这些懒加载对象的属性(getId和getClass除外)Hibernate会初始化这些代理,或用hibernate.initalize(proxy)来初始化代理对象;当关闭session后在访问懒加载的对象就会出现异常
- Hibernate3.6.2 懒加载分析
- Hibernate3延迟加载(lazy loading)详细分析与解释
- Hibernate3延迟加载机制
- Hibernate3中的属性延迟加载
- weblogic10 hibernate3.2加载错误
- Hibernate3.2(7):延迟加载
- 懒加载分析情况
- 懒加载分析情况
- 懒加载分析情况
- 懒加载分析情况
- 懒加载分析情况
- Hibernate懒加载分析
- Hibernate懒加载分析
- 懒加载原理分析
- hibernate3 动态控制 延迟加载 lazy=false
- 浅谈Hibernate3中对象的加载
- Hibernate3中加载方式的使用
- Hibernate3
- [转载] C程序的函数栈作用机理
- 一些有意思的网站和贴子
- 《C语言及程序设计》资料——C语言中数学函数
- “出错了”和报告Bug的艺术——转给产品和测试的看看,哭瞎~
- size_t
- Hibernate3.6.2 懒加载分析
- c函数调用过程原理及函数栈帧分析
- .net输出相互独立的多个柱状图(基于highcharts)
- Java-Palindrome Partitioning
- 《程序员健康指南》作者Joe Kutner:在运动中工作
- 初识python模块
- 「轻松支付,只需几步」使用 LeanCloud 云代码接入支付宝示例
- 大小端检测
- poj 3071 Football(概率dp)