`

11-Hibernate3.6.2 懒加载分析

阅读更多

      懒加载是指程序推迟访问数据库,这样做可以保证有时候不必要的访问数据库,提供性能。

一、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(); 
		} 
	}

 利用hibernateinitialize()方法将这个代理对象给初始化。

注:在使用代理对象的getId()方法和getClass()方法的时候,并不会抛出不能初始化异常,因为这两个属性并不用查询数据库。

 

 

二、关联关系下的懒加载

 1one-to-one懒加载

 一对一的懒加载并不常用,因为懒加载的目的是为了减少与数据库的交互,从而提高执行效率,而在一对一关系中,主表中的每一条数据只对应从表的一条数据库,就算都查询也不会增加多少交互的成本,而且主表不能有contrained=true,所以主表是不能懒加载的。但是从表可以有。

 实现此种懒加载必须在从对象这边同时满足三个条件:

 1lazy!=falselazy的属性有三个选项分别为:no-proxyfalseproxy

 2Constrained = true

 3fetch=select

 注:当fetch设置为join时,懒加载就会失效。因为fetch的作用是抓取方式,他有两个值分别为selectjoin,默认值为select。即在设为join时,他会直接将从表信息以join方式查询到而不是再次使用select查询,这样导致了懒加载的失效。

 

2one-to-many懒加载

 one-to-one关联不同,对one-to-many而言,主表的每一条属性都会对应从表的多条数据,这个时候懒加载就显得非常有效了。比如一个部门里面有多个员工,如果没有懒加载,每查询这个部门的时候都会查询出多个员工,这会大大增加与数据库交互的成本。所以Hbernate默认的是加入懒加载的。这就是查询集合属性的时候返回的是一个PersistentIndexed*类型对象的原因。该对象其实就是一个代理对象。当然,可以在映射文件中通过将lazy属性设为假来禁用。

Hibernate默认对one-to-many就是使用的懒加载,但用户也可以取消懒加载操作:

一:设置lazy=false;

二:设置fetch=join.

实现此种懒加载必须在从对象这边同时满足两个条件:

1lazy!=falselazy的属性有三个选项分别为:no-proxyfalseproxy

2fetch=select

 

3many-to-one懒加载

此关联关系的懒加载和one-to-one的懒加载一样都是可要可不要的,因为对执行效率的提高都不是非常明显。虽然多对一与一对一关系方式相同,但是在Hibernate中多对一时,默认是进行懒加载的。另外有一点需要注意的是懒加载并不会区分集合属性里面是否有值,即使是没有值,他依然会使用懒加载。

实现此种懒加载必须在从对象这边同时满足两个条件

1lazy!=falselazy的属性有三个选项分别为:no-proxyfalseproxy

2fetch=select

 

4many-to-many懒加载

此关联关系的懒加载和one-to-many的懒加载一样对程序的执行效率的提高都是非常明显的。

实现此种懒加载必须在从对象这边同时满足两个条件:

1lazy!=falselazy的属性有三个选项分别为:no-proxyfalseproxy

2fetch=select

能够懒加载的对象都是被改过的代理对象,当相应的对象没有关闭时,访问这些懒加载对象的属性(getIdgetClass除外)Hibernate会初始化这些代理,或用hibernate.initalize(proxy)来初始化代理对象;当关闭session后在访问懒加载的对象就会出现异常

 

 

 

  • 大小: 91.6 KB
分享到:
评论

相关推荐

    hibernate-distribution-3.6.2.Final-dist jar包

    12. **延迟加载(Lazy Loading)**:Hibernate支持懒加载机制,即当需要访问关联对象时才进行数据库查询,提高性能。 以上就是`hibernate-distribution-3.6.2.Final-dist` jar包中涉及的主耍知识点。这个包包含了...

    Hibernate Core 3.3.2.GA API (html官方英文版)

    懒加载是一种优化策略,只在真正需要时才加载关联对象,以减少内存消耗和提高性能。通过@ManyToOne和@OneToMany的fetch属性可以配置懒加载。 10. **Event Listeners(事件监听器)** Hibernate允许注册事件监听器...

    hibernate3.2+mysql+log4j

    5. 支持CGLIB和Java代理实现的透明性,增强了对懒加载和动态代理的处理。 **MySQL** MySQL是一种广泛使用的开源关系型数据库管理系统,以其高性能、稳定性、易用性和免费特性而受到欢迎。在Java应用中,MySQL常作为...

    Hibernate4.2Jar官方最新jar包

    Hibernate利用它来动态生成和修改类,比如在运行时创建代理类以实现懒加载等特性。 6. **MySQL Connector/J** (`mysql-connector-java-5.0.4-bin.jar`): 这是MySQL数据库的Java驱动程序,使得Hibernate能够连接并...

    JAVA程序开发技术

    **3.6.2 可以服务于多个客户端的多线程程序** - **示例**:多客户端并发聊天室。 #### 第四章:JDBC技术 **4.1 概述** - **定义**:Java数据库连接技术。 - **目的**:允许Java程序与各种关系数据库交互。 **4.2 ...

    通向架构师的道路(第二十五天)SSH的单元测试与dbunit的整合的例子

    <version>3.6.2 <scope>test ``` 在实际的单元测试代码中,可以使用`DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS`等配置项来调整dbunit的行为,以适应不同的测试需求。同时,dbunit提供了一系列的IDataSet接口...

    iBATIS实战

    11.1.1 Hibernate版本的DAO实现 194 11.1.2 JDBC版本的DAO实现 199 11.2 为其他数据源使用DAO模式 203 11.2.1 示例:为LDAP使用DAO 203 11.2.2 示例:为Web服务使用DAO 208 11.3 使用Spring DAO 209 11.3.1 编写代码...

    Spring攻略(第二版 中文高清版).part2

    3.6.2 解决方案 127 3.6.3 工作原理 128 3.7 在你的Bean中引入行为 132 3.7.1 问题 132 3.7.2 解决方案 132 3.7.3 工作原理 132 3.8 为你的Bean引入状态 135 3.8.1 问题 135 3.8.2 解决方案 135 ...

    Spring攻略(第二版 中文高清版).part1

    3.6.2 解决方案 127 3.6.3 工作原理 128 3.7 在你的Bean中引入行为 132 3.7.1 问题 132 3.7.2 解决方案 132 3.7.3 工作原理 132 3.8 为你的Bean引入状态 135 3.8.1 问题 135 3.8.2 解决方案 135 ...

Global site tag (gtag.js) - Google Analytics