`

Hibernate lazy加载FOR Connection

阅读更多
Hibernate集合属性的懒加载策略:

在集合属性上,可以配置懒加载策略,取值为:true/false/extra

true:默认取值,它的意思是只有在调用这个集合获取里面的元素对象时,才发出查询语句,加载其
     集合元素的数据
false:取消懒加载特性,即在加载对象的同时,就发出第二条查询语句加载其关联集合的数据
extra:一种比较聪明的懒加载策略,即调用集合的size/contains等方法的时候,hibernate
      并不会去加载整个集合的数据,而是发出一条聪明的SQL语句,以便获得需要的值,只有在
      真正需要用到这些集合元素对象数据的时候,才去发出查询语句加载所有对象的数据

 

 

以下以单向一对多映射为基础。对一方的set进行lazy的相关设置,来进行测试。

如下:

package com.bjsxt.hibernate;

import java.util.Set;

public class Classes {
	
	private int id;
	
	private String name;
	
	private Set students;
	
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Set getStudents() {
		return students;
	}

	public void setStudents(Set students) {
		this.students = students;
	}
	
	
}

 

package com.bjsxt.hibernate;

public class Student {
	
	private int id;
	
	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

 

 

Classes.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.bjsxt.hibernate.Classes" table="t_classes">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<!-- 
			<set name="students" cascade="all" order-by="id">
		 -->
		 <set name="students" lazy="extra">
			<key column="classid"/>
			<one-to-many class="com.bjsxt.hibernate.Student"/>
		</set>
	</class>
</hibernate-mapping>

 

Student.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.bjsxt.hibernate.Student" table="t_student">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
	</class>
</hibernate-mapping>

 

 

以上配置了一对多映射。

由于集合下在LAZY有三个属性值true/false/extra可以设置,下面我们分别进行测试。

1、true:默认取值,它的意思是只有在调用这个集合获取里面的元素对象时,才发出查询语句,加载其
     集合元素的数据

 

package com.bjsxt.hibernate;

import java.util.Iterator;
import java.util.Set;

import org.hibernate.Session;

import junit.framework.TestCase;

/**
 * 保持lazy的默认值
 * @author Administrator
 *
 */
public class CollectionLazyTest1 extends TestCase {
	
	public void testLoadClasses1() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//不会发出查询sql
			Classes classes = (Classes)session.load(Classes.class, 1);
			
			//会发出一条查询sql,加载数据到classes
			System.out.println("班级:【" + classes.getName() + "】  拥有的学生:");
			
			//不会发出查询sql
			Set students = classes.getStudents();
			
			//会发出一条查询sql,加载数据到Students
			for (Iterator iter = students.iterator(); iter.hasNext();) {
				Student student = (Student)iter.next();
				System.out.println(student.getName());
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
	public void testLoadClasses2() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//不会发出查询sql
			Classes classes = (Classes)session.load(Classes.class, 1);
			
			//会发出一条查询sql,加载数据到classes
			System.out.println("班级:【" + classes.getName() + "】  拥有的学生总数:");

			//不会发出查询sql	
			Set students = classes.getStudents();
			
			//会发出一条查询sql,加载全部的数据到Students
			System.out.println(students.size());
			
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
}

 上面两个方法执行的结果为:

testLoadClasses1结果:

Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
班级:【班级】  拥有的学生:
Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_ from t_student students0_ where students0_.classid=?
学生_6
学生_9
学生_2
学生_0
学生_4
学生_1
学生_8
学生_7
学生_5
学生_3

 

testLoadClasses2结果:

Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
班级:【班级】  拥有的学生总数:
Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_ from t_student students0_ where students0_.classid=?
10

 

2、false:取消懒加载特性,即在加载对象的同时,就发出第二条查询语句加载其关联集合的数据

package com.bjsxt.hibernate;

import java.util.Iterator;
import java.util.Set;

import org.hibernate.Session;

import junit.framework.TestCase;

/**
 * 设置集合上的lazy=false
 * @author Administrator
 *
 */
public class CollectionLazyTest2 extends TestCase {
	
	public void testLoadClasses1() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//不会发出查询sql
			Classes classes = (Classes)session.load(Classes.class, 1);
			
			//会发出两条查询sql,加载数据到classes和Students中
			System.out.println("班级:【" + classes.getName() + "】  拥有的学生:");
			
			//不会发出查询sql
			Set students = classes.getStudents();
			
			//不会发出查询sql
			for (Iterator iter = students.iterator(); iter.hasNext();) {
				Student student = (Student)iter.next();
				System.out.println(student.getName());
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
	public void testLoadClasses2() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//不会发出查询sql
			Classes classes = (Classes)session.load(Classes.class, 1);
			
			//会发出两条查询sql,加载数据到classes和Students中
			System.out.println("班级:【" + classes.getName() + "】  拥有的学生总数:");

			//不会发出查询sql	
			Set students = classes.getStudents();
			
			//不会发出查询sql	
			System.out.println(students.size());
			
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
}

 这里在testLoadClasses1方法当调用classes.getName()时注意,此时才发出两条SQL,如下 :

Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_ from t_student students0_ where students0_.classid=?
班级:【班级】  拥有的学生:
学生_3
学生_9
学生_4
学生_6
学生_5
学生_1
学生_8
学生_0
学生_2
学生_7

 而testLoadClasses2的结果也是如下:注意这两个SQL也是在调用classes.getName时发出的,后面打印出students.size没有再次发出SQL。这也正好说明:在加载对象的同时,就发出第二条查询语句加载其关联集合的数据

Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_ from t_student students0_ where students0_.classid=?
班级:【班级】  拥有的学生总数:
10

 

 

3、extra:一种比较聪明的懒加载策略,即调用集合的size/contains等方法的时候,hibernate
      并不会去加载整个集合的数据,而是发出一条聪明的SQL语句,以便获得需要的值,只有在
      真正需要用到这些集合元素对象数据的时候,才去发出查询语句加载所有对象的数据

package com.bjsxt.hibernate;

import java.util.Iterator;
import java.util.Set;

import org.hibernate.Session;

import junit.framework.TestCase;

/**
 * 设置集合上的lazy=extra
 * @author Administrator
 *
 */
public class CollectionLazyTest3 extends TestCase {
	
	public void testLoadClasses1() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//不会发出查询sql
			Classes classes = (Classes)session.load(Classes.class, 1);
			
			//会发出一条查询sql,加载数据到classes
			System.out.println("班级:【" + classes.getName() + "】  拥有的学生:");
			
			//不会发出查询sql
			Set students = classes.getStudents();
			
			//会发出一条查询sql,加载数据到students
			for (Iterator iter = students.iterator(); iter.hasNext();) {
				Student student = (Student)iter.next();
				System.out.println(student.getName());
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
	public void testLoadClasses2() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//不会发出查询sql
			Classes classes = (Classes)session.load(Classes.class, 1);
			
			//会发出一条查询sql,加载数据到classes
			System.out.println("班级:【" + classes.getName() + "】  拥有的学生总数:");

			//不会发出查询sql	
			Set students = classes.getStudents();
			
			//会发出一条较为智能的查询sql,如:
			//select count(id) from t_student where classid =?
			System.out.println(students.size());
			
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
	public void testLoadClasses3() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//不会发出查询sql
			Classes classes = (Classes)session.load(Classes.class, 1);
			
			//会发出一条查询sql,加载数据到classes
			System.out.println("班级:【" + classes.getName() + "】  拥有的学生总数:");

			//不会发出查询sql	
			Set students = classes.getStudents();

			//迭代会发出SQL
			for (Iterator iter = students.iterator(); iter.hasNext();) {
				Student student = (Student)iter.next();
				System.out.println(student.getName());
			}
			
			//因为前面已经迭代出了所有的数据,所以以下不发出sql,与testLoadClasses2的不同就是打印总数之前是否有迭代。
			System.out.println(students.size());
			
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
}

 

testLoadClasses1结果:

Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
班级:【班级】  拥有的学生:
Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_ from t_student students0_ where students0_.classid=?
学生_2
学生_8
学生_3
学生_5
学生_4
学生_9
学生_0
学生_7
学生_1
学生_6

 testLoadClasses2结果:

Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
班级:【班级】  拥有的学生总数:
Hibernate: select count(id) from t_student where classid =?
10

 

 

可以看到当LAZY=“extra”的时候会比较智能,即students.size()的时候,会调用select count(id) from t_student where classid =?
求总数。

比较三种值设置间的区别与联系,显然第三种方法更为优化

分享到:
评论

相关推荐

    Hibernate使用指南

    * lazy loading:使用 lazy loading 来减少数据的加载次数。 * batching:使用 batching 来批量执行数据库操作。 * Query 优化:使用 Query 优化来减少数据库的查询次数。 七、 Hibernate 的应用 Hibernate 广泛...

    Hibernate较完整资料

    3. `lazy="false"` 表示实体加载策略,不启用延迟加载,意味着关联的对象在加载时会立即加载。 4. `&lt;id&gt;` 元素定义主键,`generator` 属性指定生成策略,`identity` 表示由数据库自动生成 ID。 5. `&lt;property&gt;` 元素...

    有关hibernate的论文

    Hibernate支持多种持久化策略,如懒加载(Lazy Loading)、立即加载(Eager Loading)和级联(Cascading)。懒加载可以推迟加载关联对象,直到真正需要时才从数据库获取,以优化性能;立即加载则会在加载主对象时...

    Hibernate3.3jar包

    7. **懒加载(Lazy Loading)**: Hibernate提供了一种优化策略,即延迟加载,只有在真正需要时才加载关联的对象,减少内存消耗。 8. **级联操作(Cascading)**: 可以配置实体间的级联关系,如`@OneToMany` 和 `@...

    hibernate小白极简实例

    &lt;property name="hibernate.connection.driver_class"&gt;com.mysql.jdbc.Driver&lt;/property&gt; ... &lt;/hibernate-configuration&gt; ``` 6. **Session与事务(Transaction)** `Session`是工作单元,用于执行数据库...

    Hibernate 项目图片资料

    例如,设置`&lt;property name="hibernate.connection.url"&gt;`来指定数据库URL。 4. **SessionFactory 和 Session** SessionFactory是线程安全的,负责生成Session实例。Session是工作单元,与数据库进行交互,包括...

    hibernate3.5.6开发包

    10. **性能优化**:包括延迟加载(lazy loading)、批处理(batch processing)、预加载(preloading)、连接池(connection pool)等技术,都是Hibernate性能优化的重要手段。 **标签:“Hibernate”** 在实际...

    Hibernate框架搭建及数据库相关操作

    1. **懒加载**:延迟加载(Lazy Loading)允许只在需要时加载关联的对象,减少数据库交互。 2. **级联操作**:通过 `@ManyToOne`, `@OneToMany`, `@OneToOne` 等注解设置级联行为,比如删除父对象时自动删除子对象...

    hibernate核心代码

    10. **延迟加载(Lazy Loading)**: Hibernate 的懒加载机制可以在需要时才加载关联对象,提高性能。 通过以上关键点,我们可以理解Hibernate的核心运作机制,从而高效地进行数据库操作。在实际开发中,还需要...

    使用Hibernate访问sqlserver数据库

    9. **性能优化**: Hibernate提供了许多优化策略,如缓存(一级缓存和二级缓存)、延迟加载(Lazy Loading)、批处理等,以提高性能和减少数据库访问。 在`hbtest`这个项目中,可能包含了用于演示如何使用Hibernate...

    最全的hibernate架包jar

    11. **延迟加载(Lazy Loading)**:Hibernate允许对象的属性或关联关系在需要时才加载,避免了不必要的数据库访问,提高了性能。 在使用Hibernate 3.2.0 GA时,你需要了解其API的使用方法,配置文件的编写,以及...

    hibernate_reference

    - **Fetch Strategies:** 控制Hibernate加载关联对象的方式,如eager(急切加载)和lazy(延迟加载)。 - **Batch Processing:** 通过批量处理减少与数据库的交互次数,提高效率。 - **Second-Level Cache:** ...

    HibernateDemo

    7. **懒加载(Lazy Loading)与级联操作(Cascading)**:懒加载是一种优化策略,只有当真正需要访问关联对象时,才会执行数据库查询。级联操作允许在一个实体的操作(如保存、删除)影响到其关联的其他实体。 在...

    Hibernate需要的架包

    **七、延迟加载(Lazy Loading)** Hibernate 支持懒加载,即只有在真正需要访问关联对象时,才会去数据库加载。这可以有效避免加载大量不必要的数据,提高系统性能。 **八、事务管理** Hibernate 支持JTA(Java ...

    hibernate开发帮助文档

    7. **懒加载(Lazy Loading)**:延迟加载策略,只在需要时加载关联对象,以提高性能。 8. **缓存(Caching)**:分为一级缓存(Session级别)和二级缓存(SessionFactory级别),可以使用第三方缓存实现如Ehcache...

    hibernate数据库访问接口设计

    `Lazy Loading` 是一种优化策略,延迟加载关联的对象,只有在真正需要时才从数据库加载,以减少内存占用和提高性能。 ### 8. Events and Listeners Hibernate 支持事件监听机制,允许开发者在特定操作(如对象的...

    Hibernate入门 - 基础配置

    `&lt;loader&gt;`标签用于定义命名查询,这在获取或加载Person对象时会被调用。最后,`&lt;sql-insert&gt;`, `&lt;sql-update&gt;`和`&lt;sql-delete&gt;`分别定义了自定义的SQL语句,用于插入、更新和删除操作。 三、Hibernate配置基础 要...

    Hibernate 用法实例

    1. **延迟加载(Lazy Loading)**: 只在真正需要时加载关联对象,减少内存占用。 2. **批处理**: 批量保存、更新或删除,提高效率。 3. **缓存策略**: 通过合理配置缓存,减少数据库访问。 通过以上详细讲解,读者...

    hibernate3.5.4

    Hibernate 提供了多种性能优化手段,如懒加载(Lazy Loading)、批处理(Batch Processing)、缓存策略等,以减少数据库交互次数,提高系统性能。 9. **版本控制**: Hibernate 3.5.4引入了乐观锁(Optimistic ...

Global site tag (gtag.js) - Google Analytics