你在做查询的时候它可以帮你关联出它的一些相应的关联对象。那么它关联这个对象的时候是在什么时候发送的这些语句以及它是如何把这些数据拿出来的?
知道延迟检索是怎么回事了,而且它也能够产生这个代理对象。当你用这个代理对象的某个属性的时候它才会初始化。那么代理对象由谁来生成呢?由E:北风网hibernate_day03WebRootWEB-INFlibjavassist-3.12.0.GA.jar这个jar包来生成。
关联级别的检索策略:
package cn.itcast.test;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.itcast.utils.HibernateUtils;
import cn.itcast.vo.Customer;
import cn.itcast.vo.Order;
/**
* Hibernate的抓取策略
* @author zhongzh
*
*/
public class HibernateDemo2 {
@Test
/*
* 在<set>集合上配置
* * fetch="subselect" lazy="true"
* * 使用subselect的时候 需要使用query接口进行测试.
* * 如果查询一个客户 查询多个客户.
* 如果有多个客户:
* * select * from orders where cno in (1,2,3);
* 如果只有一个客户:
* * select * from orders where cno = 1;
*/
public void demo7(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
List<Customer> list = session.createQuery("from Customer").list();
for (Customer customer : list) {
System.out.println(customer.getOrders().size());
}
tx.commit();
session.close();
}
@Test
/*
* 在<set>集合上配置
* * fetch="select" lazy="extra"
* * lazy:extra:极其懒惰.要订单的数量
*/
public void demo6(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer = (Customer) session.get(Customer.class, 1);
// select count(*) from orders where cno = ?;
System.out.println(customer.getOrders().size());
//发送查询订单的SQL.
for (Order order : customer.getOrders()) {
System.out.println(order);//使用订单的是时候它才会发送查询订单的SQL.
}
tx.commit();
session.close();
}
@Test
/*
* 在<set>集合上配置
* * fetch="select" lazy="false"
* * lazy:false:关联对象的检索不使用延迟
*/
public void demo5(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// 发送多条SQL,查询关联对象.
Customer customer = (Customer) session.get(Customer.class, 1);
// 使用订单的时候又发送一条查询这个客户的订单的SQL
System.out.println(customer.getOrders().size());
tx.commit();
session.close();
}
@Test
/*
* 在<set>集合上配置
* * fetch="select" lazy="true"
* * lazy:true-使用延迟检索
* * 发送多条SQL,查询关联对象
*/
public void demo4(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// 发送一条只查询客户的SQL
Customer customer = (Customer) session.get(Customer.class, 1);
// 使用订单的时候又发送一条查询这个客户的订单的SQL
System.out.println(customer.getOrders().size());
tx.commit();
session.close();
}
@Test
/*
*
* <set>配置fetch="join" lazy就会被忽略!!!!
* * 发送迫切左外连接查询两个表.
*/
public void demo3(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//直接发送一条迫切左外连接。其实迫切左外连接和左外连接的SQL语句是一样的.只不过封装的对象不一样.
//迫切左外连接封装到一个对象里.而普通左外连接封装到一个数组里.
//只要一查客户订单就出来了.
/*
* Hibernate:
select
customer0_.cid as cid0_1_,
customer0_.cname as cname0_1_,
orders1_.cno as cno0_3_,
orders1_.oid as oid3_,
orders1_.oid as oid1_0_,
orders1_.addr as addr1_0_,
orders1_.cno as cno1_0_
from
Customer customer0_
left outer join
orders orders1_
on customer0_.cid=orders1_.cno
where
customer0_.cid=?
*/
Customer customer = (Customer) session.get(Customer.class, 1);
System.out.println(customer.getOrders().size());
tx.commit();
session.close();
}
@Test
/*
*
* <set>没有配置fetch 和 lazy情况
*
*/
public void demo2(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer = (Customer) session.get(Customer.class,1);// 发送查询客户的SQL.
//System.out.println(customer.getCname());
System.out.println(customer.getOrders().size());// 使用了客户的订单的时候,才会发送查询订单的SQL. 又发送一条SQL 去查询客户的关联的订单.
tx.commit();
session.close();
}
@Test
/*区分立即检索和延迟检索
*
*
*/
public void demo1(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//立即检索
//
/* Customer customer = (Customer) session.get(Customer.class, 1);
System.out.println(customer);*/
//延迟检索:
// 持久化类如果设置为final 延迟检索就失效了.因为不能生成代理对象
// 在Customer.hbm.xml中在<class>标签上配置lazy="false"不支持延迟检索,就会立即检索.
Customer customer = (Customer) session.load(Customer.class, 1);//这是类级别的检索
//System.out.println(customer);//如果这一行注释的话根本就不会发送SQL语句,你执行完了它也不会发送,因为你根本没有
//用到它里面的属性。
//初始化代理对象 发送SQL语句 产生代理对象 那肯定就能拿出来了
//System.out.println(customer.getCname());
//还可以这样来初始化代理对象
Hibernate.initialize(customer);//当你初始化的时候它才会发送SQL语句
tx.commit();
session.close();
}
}
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.itcast.vo"><!-- 如果这里配置了包名下面可以不用写 --> <!-- <hibernate-mapping> --> <!-- <class name="cn.itcast.hibernate3.demo2.Customer" table="customer"> --> <!-- <class name="cn.itcast.vo.Customer"> --> <class name="Customer" lazy="true"> <!-- 配置唯一标识 --> <id name="cid" column="cid"> <generator class="native"/> </id> <!-- 配置普通属性 --> <property name="cname" column="cname" length="20"/> <!-- 建立映射 --> <!-- 配置一个集合 <set>的name Customer对象中的关联对象的属性名称. --> <!-- 这里把级联去掉 要最简短的配置 <set name="orders" cascade="save-update" inverse="true"> --> <set name="orders" cascade="save-update" fetch="subselect" lazy="true"> <!-- <key>标签中column:用来描述一对多多的一方的外键的名称. --> <key column="cno"></key> <!-- 配置一个<one-to-many>标签中class属性:订单的类的全路径 --> <!-- <one-to-many class="cn.itcast.hibernate3.demo2.Order"/> --> <one-to-many class="cn.itcast.vo.Order"/> </set> </class> <!-- 命名查询的方式 --> <query name="findAll"> from Customer </query> <!-- 这里要写sql语句 <sql-query> </sql-query> --> </hibernate-mapping>
package cn.itcast.vo; import java.util.HashSet; import java.util.Set; /** * 客户的实体: * @author 姜涛 * */ public class Customer { private Integer cid; private String cname; public Customer() {//无参构造函数 super(); // TODO Auto-generated constructor stub } public Customer(String cname) {//有参构造 super(); this.cname = cname; } // 一个客户有多个订单. private Set<Order> orders = new HashSet<Order>(); public Integer getCid() { return cid; } public void setCid(Integer cid) { this.cid = cid; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } public Set<Order> getOrders() { return orders; } public void setOrders(Set<Order> orders) { this.orders = orders; } //@Override public String toString() {//客户这里打印也打印出订单的集合。这是死循环了,所以这里应该去掉一方的打印。 /* return "Customer [cid=" + cid + ", cname=" + cname + ", orders=" + orders + "]";*/ return "Customer [cid=" + cid + ", cname=" + cname + "]";//客户这里去掉订单集合的打印 } //测试迫切内连接的封装效果。重写toString()方法 /* @Override public String toString() { return "Customer [cid=" + cid + ", cname=" + cname + ", orders=" + orders + "]"; }*/ }
package cn.itcast.vo; /** * 订单的实体: * @author 姜涛 * */ public class Order { private Integer oid; private String addr; // 订单属于某一个客户.放置一个客户的对象. private Customer customer; public Integer getOid() { return oid; } public void setOid(Integer oid) { this.oid = oid; } public String getAddr() { return addr; } public void setAddr(String addr) { this.addr = addr; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } //@Override public String toString() {//订单这边又打印客户了。这是死循环了,所以这里应该去掉一方的打印。 return "Order [oid=" + oid + ", addr=" + addr + ", customer=" + customer + "]"; } //测试迫切内连接的封装效果。重写toString()方法 /* @Override public String toString() {//两边不能同时打印,不然容易出问题 return "Order [oid=" + oid + ", addr=" + addr + "]"; }*/ }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <!-- <class name="cn.itcast.hibernate3.demo2.Order" table="orders"> --> <class name="cn.itcast.vo.Order" table="orders"> <!-- 配置唯一标识 --> <id name="oid" column="oid"> <generator class="native"/> </id> <!-- 配置普通属性 --> <property name="addr" column="addr" length="50"/> <!-- 配置映射 --> <!-- <many-to-one>标签 name :关联对象的属性的名称. column :表中的外键名称. class :关联对象类的全路径 --> <!-- <many-to-one name="customer" column="cno" class="cn.itcast.hibernate3.demo2.Customer"/> --> <many-to-one name="customer" column="cno" class="cn.itcast.vo.Customer"/> </class> </hibernate-mapping>