hibernate一对多

关联关系

关联指的是类之间的引用关系。如果类A与类B关联,那么被引用的类B将被定义为类A的属性。

关联的分类:关联可以分为一对一、一对多/多对一、多对多关联

常见的订单与订单项就是典型的一对多

实例(订单与订单项)

在数据库里有两个表,一个订单表一个订单项表。

实体类与对应的配置文件

Order订单
一个订单对应多个订单项

package com.hu.three.entity;

import java.util.ArrayList;
import java.util.List;

public class Order {
	private Integer orderId;
	private String orderNo;
	private Integer initChildren = 0;//0是懒加载,1是非懒加载
	
	public Integer getInitChildren() {
		return initChildren;
	}
	public void setInitChildren(Integer initChildren) {
		this.initChildren = initChildren;
	}
	//建立关联关系  一个订单对应多个订单项
	private List<OrderItem> orderItem =  new ArrayList<>();
	
	public List<OrderItem> getOrderItem() {
		return orderItem;
	}
	public void setOrderItem(List<OrderItem> orderItem) {
		this.orderItem = orderItem;
	}
	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;
	}
	@Override
	public String toString() {
		return "Order [orderId=" + orderId + ", orderNo=" + orderNo + "]";
	}
}

Orderitem订单项
一个订单项对应多个订单

package com.hu.three.entity;

public class OrderItem {
	private Integer orderItemId;
	private Integer productId;
	private Integer quantity;
	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 getQuantity() {
		return quantity;
	}
	public void setQuantity(Integer quantity) {
		this.quantity = quantity;
	}
	public Integer getOid() {
		return oid;
	}
	public void setOid(Integer oid) {
		this.oid = oid;
	}
	@Override
	public String toString() {
		return "OrderItem [orderItemId=" + orderItemId + ", productId=" + productId + ", quantity=" + quantity
				+ ", oid=" + oid + "]";
	}
}

订单配置文件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 name="com.hu.three.entity.Order" table="t_hibernate_order">
		<id name="orderId" type="java.lang.Integer" column="order_id">
			<generator class="increment" />
		</id>
		<property name="orderNo" type="java.lang.String" column="order_no">
		</property>
		<!-- 
			 bag标签:
			 	lazy:是否懒加载,默认是懒加载的true  懒汉模式
			 	name:类的关联属性名
			 	cascade:级联关系  级联新增与修改
			 	inverse:关联关系交给对方控制  默认是true,当前类不维护关联关系
				
				子标签key:
				column:主表的主键,从表的外键
				
				子标签one-to-many:
				class:外键对应的实体类
		 -->
		<bag name="orderItem" inverse="true" lazy="true" outer-join="false" cascade="save-update">
			<!-- 从表的外键 -->
			<key column="oid"></key>
			<one-to-many class="com.hu.three.entity.OrderItem"/>
		</bag>
		
	</class>

</hibernate-mapping>

订单项配置文件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 name="com.hu.three.entity.OrderItem" table="t_hibernate_order_item">
		<id name="orderItemId" type="java.lang.Integer" column="order_item_id">
			<generator class="increment" />
		</id>
		<property name="productId" type="java.lang.Integer" column="product_id">
		</property>
		<property name="quantity" type="java.lang.Integer" column="quantity">
		</property>

		<!-- insert="false" update="false" 放弃对表的维护 -->

		<property name="oid" type="java.lang.Integer" column="oid" insert="false" update="false">
		</property>

		<many-to-one name="order" class="com.hu.three.entity.Order"
			column="oid"></many-to-one>
	</class>
</hibernate-mapping>

测试方法dao

package com.hu.three.dao;

import java.util.List;

import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.hu.three.entity.Order;
import com.hu.three.entity.OrderItem;
import com.hu.two.util.SessionFactoryUtils;

public class DemoDao {
	/**
	 * 为了测试关系型映射文件配置准确
	 * 	讲解insert=false,update=false的用途
	 * @param order
	 * @return
	 */
	public Integer addOrder(Order order) {//增加订单
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		Integer oid = (Integer)session.save(order);
		transaction.commit();
		session.close();
		return oid;
	}
	
	public Integer addOrderItem(OrderItem orderItem) {//增加订单项
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		Integer otid = (Integer)session.save(orderItem);
		transaction.commit();
		session.close();
		return otid;
	}
	
	
	
	/**
	 * 为了讲解懒加载的问题(hibernate3.0后所有查询方式默认采用的是懒加载方式)
	 * 	1、查单个时存在问题,代理对象已经关闭
	 * 	2、查多个存在问题,有性能的问题
	 * @param order
	 * @return
	 */
	public Order getOrder(Order order) {//单个查
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		Order o = session.get(Order.class, order.getOrderId());
		if(o != null && new Integer(1).equals(order.getInitChildren())) {
			//强制加载关联对象
			Hibernate.initialize(o.getOrderItem());
//			System.out.println(o.getOrderItems());
		}
		transaction.commit();
		session.close();
		return o;
	}
	
	public List<Order> getOrderList() {//订单项查全部
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		List<Order> list = session.createQuery("from Order").list();
		transaction.commit();
		session.close();
		return list;
	}
	
	/**
	 * z主表的数据不能随便删除,得先删除从表中对应信息,才能删除主表的信息。
	 * @param order
	 */
	public void delOrder(Order order) {//删除
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		Order order2 = session.get(Order.class, order.getOrderId());
		for (OrderItem oi : order2.getOrderItem()) {
			session.delete(oi);
		}
		session.delete(order2);
//		session.delete(order);
		transaction.commit();
		session.close();
	}

}

编写Junit测试

package com.hu.three.dao;

import static org.junit.Assert.*;

import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.hu.three.entity.Order;
import com.hu.three.entity.OrderItem;

/**
 * @Before没测试一个@test标记的方法,都会调用之前执行一次
 * @After每测试一个@test标记的方法,都会调用之后执行一次
 * @author Administrator
 *
 */
public class DemoDaoTest {
	 private DemoDao demodao = new DemoDao();

//	@Before
//	public void setUp() throws Exception {
//		System.out.println("加载资源的");
//	}
//
//	@After
//	public void tearDown() throws Exception {
//		System.out.println("释放资源的");
//	}

	@Test
	public void testAddOrder() {//加入订单的同时加入订单项
		Order order = new Order();
		order.setOrderNo("p30");
		OrderItem orderitem = null;
		for (int i = 0; i < 6; i++) {
			orderitem = new OrderItem();
			orderitem.setProductId(1+i);
			orderitem.setQuantity(2+i);
//			维护关联关系
			orderitem.setOrder(order);
			order.getOrderItem().add(orderitem);
			
		}
		demodao.addOrder(order);
	}

	@Test
	public void testAddOrderItem() {//向原有的订单加入订单项
		OrderItem orderitem = null;		
		for (int i = 0; i < 6; i++) {
			orderitem = new OrderItem();
			orderitem.setProductId(1+i);
			orderitem.setQuantity(2+i);
//			维护关联关系
			Order order = new Order();
			order.setOrderId(2);
			order.getOrderItem().add(orderitem);
			orderitem.setOrder(order);			
			demodao.addOrderItem(orderitem);
		}	
	}

	@Test
	public void testGetOrder() {
		Order order = new Order();
		order.setOrderId(1);
		order.setInitChildren(1);
		Order o = this.demodao.getOrder(order);
//		failed to lazily initialize a collection of role:没有加载数组集合
//		com.hu.three.entity.Order.orderItem, 
//		could not initialize proxy - no Session 没有使用proxy 因为什么session对象
		//原有操作了两次数据库:当lazy=false的时候,会让hibernate执行完两次操作session才会关闭
		//当lazy=true的时候,会让hibernate执行完一次操作,session才会关闭
		//从上面看lazy=false更好,但为什么lazy默认等于true呢?
		//出于性能的考虑,所以hibernate3.0之后的lazy这个属性,并让他默认等于true,也就是说不加载关联属性
		List<OrderItem> orderItem = o.getOrderItem();
		for (OrderItem orderItem2 : orderItem) {
			System.out.println(orderItem2);
		}
		System.out.println(o);
	}

	@Test
	public void testGetOrderList() {
		List<Order> orderList = this.demodao.getOrderList();
		for (Order order : orderList) {
			for (OrderItem orderItem2 : order.getOrderItem()) {
				System.out.println(orderItem2);
			}
			System.out.println(order);
		}
	}

	@Test
	public void testDelOrder() {
		Order order = new Order();
		order.setOrderId(3);
		this.demodao.delOrder(order);
	}

}

一对多执行原理

<!-- 
	hibernate框架一对多的执行原理:
		1.对hibernate.cfg.xml进行建模,得到sessionfactory对象
		2.并且拿到mapping  resource里的内容
		3.拿到了Order.hbm.xml配置文件
		4.可以再次建模,拿到com.hu.three.entity.Order,以及t_hibernate_order类的属性,以及列段
		5.生成动态的sql:select orderId,order No from t_hibernate_order;
			执行sql最终得到meterdate源数据模型
			orderId   orderNo
			   1		 p20
			   2		 p30
			   .............
		6.Order o1 = Class.forName("com.hu.tree.entity.Order").newInstance;
			o1.setOrderId(1);
			o1.setOrderNo("p20");
			.....
			最终得到:
			List<Order> list = new ArrayList();
			list.add(o1);
			
			最终list中的所有order实例都有值了,(这里只是处理表里面的非外键列段原理完全跟base到一样)
			
		7.处理关联关系:OrderItem  oid   com.hu.three.entity.OrderItem
	 	  通过one-to-many 这个标签以及class对应的全路径名会找到class对应的全路径对应的专属配置文件
	 	  也就是找到了Order.item.xml 这个文件,拿到了它之后就可以拿到table t_hibernate_order_Item
	 	  
	 	8.select * from t_hibernate_order_Item;
	 		最终得到了一个List<OrderItem> orderItems,(跟第56步一样的)
	 	
	 	9.给Order的关联关系属性赋值
	 	List<order> list = new ArrayList();
	 	for(Order o : list){
	 		o.setOrderItem(orderItem);
	 	}
	 	
	 	总结:这里面使用了非常多的反射,所以说它的性能是非常差的。建模也使用了很多次。
	 	
	 -->

懒汉模式

懒汉模式其实是单链模式里面的一种,而为什么叫做懒汉模式呢?其实它有一个特性,就是当它需要的时候就“创建”不需要的时候就不管他。就一个例子:
懒汉模式:类加载是不创建实例,用户获取时才真正判断是否为空,如果为空才创建实例

public class Singleton2 {
    //构造方法私有化,不允许外面直接创建对象
    private Singleton2(){}
    //声明类的唯一实例,使用private static 修饰
    private static Singleton2 instance;
    //提供一个获取实例的方法,使用 public staitc修饰
    public static Singleton2 getInstance()
    {
        if(instance==null)
        {
            instance=new Singleton2();
        }
        return instance;
    }
}

public class Test {

    public static void main(String[] args) {
        Singleton2 s3=Singleton2.getInstance();
        Singleton2 s4=Singleton2.getInstance();
        if(s3==s4)
            System.out.println("s1和s2是同一个实例");
        else
            System.out.println("s1和s2不是同一个实例");
    }

}

懒加载

懒加载(lazy)就是延时加载,延迟加载。
至于为什么要用懒加载呢,
通过上面测试输出的SQL语句得出当我们要访问的数据量过大时,明显用缓存不太合适,
因为内存容量有限 ,为了减少并发量,减少系统资源的消耗,

出于性能的考虑,所以hibernate3.0之后出现lazy这个属性

lazy有三个属性:true、false、extra(集合属性时候使用)

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

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

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

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值