Hibernate:级联查询
案例:订单类和订单项类
级联查询时的问题
Lazy=true介绍 查单个时存在问题
Lazy=false介绍 查所有时存在问题 在set里把lazy=“false”也可以所报的错(com.zking.four.entity.Order.orderItems,
could not initialize proxy - no Session) <set lazy="false" name="orderItems" cascade="save-update" inverse="true">
解决方案:通过字段控制,强制加载。Hibernate.initialize()
不在order类加initOrderItems字段时,会报错
1.order类
package com.zking.four.entity;
import java.util.HashSet;
import java.util.Set;
public class Order {
private Integer orderId;
private String orderNo;
//定义一对多的关系时一定需要采用接口方式,不许使用实现类
//implements java.util.Set 代理实现的是set接口
private Set<OrderItem> orderItems=new HashSet<OrderItem>();
private Integer initOrderItem=0;//0代表懒加载 1代表立即加载
public Integer getInitOrderItem() {
return initOrderItem;
}
public void setInitOrderItem(Integer initOrderItem) {
this.initOrderItem = initOrderItem;
}
public Set<OrderItem> getOrderItems() {
return orderItems;
}
public void setOrderItems(Set<OrderItem> orderItems) {
this.orderItems = orderItems;
}
public Integer getOrderId() {
return orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
public String getOrderNo() {
return orderNo;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
}
2.orderItem类
package com.zking.four.entity;
public class OrderItem {
private Integer orderItemId;
private Integer productId;
private Integer quaneity;
private Integer oid;
private Order order;
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
public Integer getOrderItemId() {
return orderItemId;
}
public void setOrderItemId(Integer orderItemId) {
this.orderItemId = orderItemId;
}
public Integer getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public Integer getQuaneity() {
return quaneity;
}
public void setQuaneity(Integer quaneity) {
this.quaneity = quaneity;
}
public Integer getOid() {
return oid;
}
public void setOid(Integer oid) {
this.oid = oid;
}
}
3.order.hbm.xml
<?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 table="t_hibernate_order" name="com.zking.four.entity.Order">
<id name="orderId" type="java.lang.Integer" column="order_id ">
<generator class="increment"></generator>
</id>
<property name="orderNo" type="java.lang.String" column="order_no "></property>
<!--
name:实体类的类属性
cascade:用来配置维护实体类之间的关系所用
inverse:(inverse="true")关系交由反方控制 即订单项 因为现在配置的是订单,所以反方是订单项
(inverse="true") 关系由自己控制 订单
lazy="false":立即加载
-->
<set lazy="false" name="orderItems" cascade="save-update" inverse="true">
<!-- 订单项外键 -->
<key column="oid"></key>
<!-- 一个订单对应多个订单项 -->
<one-to-many class="com.zking.four.entity.OrderItem"></one-to-many>
</set>
</class>
</hibernate-mapping>
4.orderItem.hbm.xml
<?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 table="t_hibernate_order_item" name="com.zking.four.entity.OrderItem">
<id name="orderItemId" type="java.lang.Integer" column="order_item_id ">
<generator class="increment"></generator>
</id>
<property name="productId" type="java.lang.Integer" column="product_id "></property>
<property name="quaneity" type="java.lang.Integer" column="quantity "></property>
<property name="oid" type="java.lang.Integer" column="oid" insert="false" update="false"></property>
<many-to-one name="order" class="com.zking.four.entity.Order" column="oid"></many-to-one>
</class>
</hibernate-mapping>
5.dao方法
public class OrderDao(){
//单个查
public Order getOrder(Order order) {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
Order o = session.get(Order.class,order.getOrderId());
if(o!=null&&new Integer(1).equals(order.getInitOrderItem())) {
Hibernate.initialize(o.getOrderItems()); //默认强制加载
}
transaction.commit();
session.close();
return o;
}
//查所有
public List<Order> listOrder() {
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
System.out.println(123);
List list = session.createQuery("from Order").list();
System.out.println(345);
transaction.commit();
session.close();
return list;
}
}
6.测试类:
public class OrderDaoTest {
private OrderDao orderDao=new OrderDao();
private OrderItem orderItem=new OrderItem();
private Order order=new Order();
/**
* com.zking.four.entity.Order.orderItems,
* could not initialize proxy - no Session
* 懒加载
*
* hibernate3 以后默认是懒加载 性能调优 关联的东西出不来
*
*
*/
@Test
public void testGetOrder() {
order.setOrderId(2);
order.setInitOrderItem(1);
Order o = this.orderDao.getOrder(order);
System.out.println(o.getOrderNo());
System.out.println(o.getOrderItems().size());
for (OrderItem oi : o.getOrderItems()) {
System.out.println(oi.getProductId());
}
}
/**
*
* 在单查订单的时候,会默认查询订单项,sql语句就会执行很多次 耗性能
*
* Lazy=false 可以解决报错问题 使懒加载变为立即加载 但是性能差
*/
@Test
public void testListOrder() {
List<Order> listOrder = this.orderDao.listOrder();
for (Order o : listOrder) {
System.out.println(o.getOrderNo());
System.out.println(o.getOrderItems().size());
for (OrderItem oi : o.getOrderItems()) {
System.out.println(oi.getProductId());
}
}
}
}
单个查结果:
查所有结果:
查询所有,是有n条数据就执行了n+1次sql查询语句(一条订单查询,n条订单项查询)
查询的解决:只要把set里的lazy设置为false使懒加载变成立即加载就可以实现查所有的方法了,但是因为sql语句执行的多了,功能性能就差了
<set lazy="false" name="orderItems" cascade="save-update" inverse="true">