Hibernate检索策略之类级别检索策略

本文深入探讨Hibernate中懒加载与立即加载的区别,通过具体代码示例解释类级别检索及延迟检索的工作原理,并展示如何通过配置实现懒加载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.立即检索:当执行到session.load(Class,Index)语句时,立即执行了Sql语句操作。

2.延迟检索:当执行到session.load(Class,Index)语句时,没有立即执行了Sql语句操作,只有当访问到对象的数据库里的信息的时候才进行Sql操作。


类级别检索:

注意:

1.类级别检索时, 当查询方法为get方法时,类级别的懒加载是对get方法无效的。

2.查询的对象,并不是被查询对象的本生,而是Hibernate动态生成的一个代理类,并且继承了被查询对象。  只有延迟检索才会产生代理,立即检索是不会产生代理类的。


Customer类:(get和set省略)

public class Customer {
	private Integer id;
	private String fname;
	private String lname;
	private Integer age;
	private Date birthday;
	private boolean married;
	private byte[] photo;
	private String description;
	private Set<Order> set = new HashSet<Order>();
}

Customer.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.xxc.domain.Customer" table="Customers" lazy="true">
		<id name="id" column="id" type="integer">
			<generator class="native"></generator>
		</id>
		<property name="name" column="name" type="string" length="20" access="property"/>
		<property name="birthday" column="birthday" type="date"/>
		<property name="age" column="age" type="integer" length="20"/>
		<property name="description" column="description" type="text" />
		<property name="married">
			<column name="married" sql-type="int(20)"></column>
		</property>
		<property name="photo">
			 <!-- property表的column属性和子元素column是互斥的,只能用其一 -->
			<column name="photo" sql-type="longblob"></column>
		</property>
	</class>
</hibernate-mapping>


Order类:(get和set省略)

public class Order {
	private Integer id;
	private String orderNumber;
	private float price;
	/* 建立从Order到Customer之间多对一关联关系 */
	private Customer customer ;
}


Order.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.xxc.domain.Order" table="Orders" lazy="true">
		<id name="id" column="id" type="integer">
			<generator class="native"></generator>
		</id>
		<property name="orderNumber" column="orderNumber" type="string" length="20"/>
		<property name="price" column="price" type="float"/>
		<!-- 映射从Order到Customer之间多对一关联关系 -->
		<many-to-one name="customer" class="com.xxc.domain.Customer" column="cid" cascade="save-update" />
	</class>
</hibernate-mapping>


测试类:

package com.xxc.app;

import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.BeforeClass;
import org.junit.Test;

import com.xxc.domain.Customer;
import com.xxc.domain.Order;

public class App {
	private static SessionFactory sf = null;
	
	@BeforeClass
	public static void initialize(){
		Configuration config = new Configuration();
		/*  也可以写成这样的形式
		 *	sf = config.addClass(Customer.class).addClass(Order.class).buildSessionFactory();
		 */
		
		config.addClass(Customer.class);
		config.addClass(Order.class);
		sf = config.buildSessionFactory();
		
	}
	
	@Test
	public void iniDB(){
		Session s = sf.openSession();
		Transaction t = s.beginTransaction();
		Customer c = new Customer();
		c.setAge(20);
		s.save(c);
		Order o  = null;
		for(int i = 0 ; i < 10 ; i++){
			o = new Order();
			o.setOrderNumber("No:"+i);
			o.setPrice(500f);
			o.setCustomer(c);
			c.getSet().add(o);
			s.save(o);
		}
		t.commit();
		s.close();
	}
	
	@Test
	public void testJianSuoCeLue(){
		Session s = sf.openSession();
		Transaction t = s.beginTransaction();
		
		Order o= (Order) s.load(Order.class, 1);
		//Order o = (Order) s.get(Order.class, 1); 当查询方法为get方法时,类级别的懒加载是对get方法无效的。
		
		/*
		 * 那么既然当执行o.getClass()和o.getId()时,都没有执行sql语句,那为何o是有值的?(反之o.getClass()肯定要抛NullPoiontException)
		 * 从打印o.getClass()可看出,其实o并不是Order类,而是Order_$$_javassist_1
		 * 这个代理类是由Hibernate动态的创建一个代理类去继承Order而来的,这个代理类可以监测到session是否关闭
		 */
		System.out.println(o.getClass());//当class标签lazy=true这句话还没执行sql,因为获取这个信息不需要进行数据库查询后才能得出
		System.out.println(o.getId());//当class标签lazy=true这句话还没执行sql,因为id在你指定查询条件的时候,load第二个参数已经手动指定了,也不需要查询数据库才能得出结果的。
	//	System.out.println(o.getPrice());//当class标签lazy=true只有执行到这句话的时候,才会进行sql操作,因为这个信息只有查询数据库才能获取。
		
		//手动的进行代理类的初始化工作
		if(! Hibernate.isInitialized(o)){//判断指定类是否初始化了
			Hibernate.initialize(o);//若没有,则进行初始化,其实就是进行数据库的查询操作,操作此对象的数据库信息
		}
		
		t.commit();
		s.close();
		
		System.out.println(o.getPrice());//假如将查询对象的操作放在这里
		/*	会报以下异常:没有session,不能初始化代理
		 *  LazyInitializationException:42 - could not initialize proxy - no Session
		 */
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值