hibernate 一对多/多对一 级联新增,查询

1. 什么是关联(association)
关联指的是类之间的引用关系。如果类A与类B关联,那么被引用的类B将被定义为类A的属性。例如:
public class A{
private B b = new B;
public A(){}
}

2.关联的分类:关联可以分为一对一、一对多/多对一、多对多关联
关联是有方向的

#关键点都在数据库中的外键上面

3案例 .如何建立订单项和订单一对多双向关联

1 定义实体及映射文件
Order
hibernate 一对多/多对一 级联新增,查询

OrderItem
hibernate 一对多/多对一 级联新增,查询

映射类
Order.hbml.xml
hibernate 一对多/多对一 级联新增,查询

OrderItem.hbml.xml
hibernate 一对多/多对一 级联新增,查询
注意:在Hibernate当中定义实体对象的集合属性时,只能使用接口而不能使用类

2 建立订单到订单项的一对多关联关系 Order.hbml.xml

hibernate 一对多/多对一 级联新增,查询

3 建立订单项到订单的多对一关联关系 OrderItem.hbml.xml
hibernate 一对多/多对一 级联新增,查询

4. 以订单和订单项的一对多双向关联为例,讲解Set元素中的cascade|inverse|outter-join|lazy属性作用
1> lazy:默认值为true,true延迟加载,false立即加载(一般设置为true,不使用立即加载,因为影响查询性能)

2> outter-join:默认值为false,true使用左外联接查询关联的(但一般不用,因为当我们把该属性设置为true时,所有的查询语句都会默认左外联,那样性能不高)

3> inverse:默认值为false,true表示将对方设置为主控方(一对多双向关联中一般将多方设置为主控方,这样可以减少SQL语句的数量,减少多余的操作)

4 >cascade:用来控制如何操作关联的持久化对象的

4.1 none:保存,更新或删除当前对象时,忽略其它关联的对象
4.2 save-update:保存、更新时级联保存所有的临时对象,并且级联更新关联的游离对象
4.3 delete:通过session的delete方法删除当前对象,级联删除关联的对象
4.4 all:等于save-update操作+delete操作

级联新增
外键处理的三种方式
1、删除从表对应的实体类中的外键属性(不建议)
2、在配置的xml中外键属性上添加 insert=false,update=false的设置。
3、在配置的xml中的manyToOne标签中添加insert=false,update=false的设置。

(数据库的一个字段对应一个描述 insert=“false” 否则报错:epeated column in mapping for entity 列重复)

级联新增 casecade=save-update

级联查询
级联查询时的问题 lazy默认trues
Lazy=true介绍 查单个时存在问题(session关闭了)
Lazy=false介绍 查所有时存在问题(性能低)

解决方案:通过字段控制,强制加载。Hibernate.initialize()

普通删除
先删除外键再删除主键

dao方法

package com.zking.four.dao;

import java.util.List;

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

import com.zking.four.entity.Order;
import com.zking.four.entity.OrderItem;
import com.zking.two.util.SessionFactoryUtil;

public class OrderDao {

/**
 * 新增订单项
 */	
public  Integer addOrderItem(OrderItem orderItem) {
	Session session = SessionFactoryUtil.getSession();
	Transaction transaction = session.beginTransaction();
	
	Integer otid = (Integer) session.save(orderItem);
	
	transaction.commit();
	SessionFactoryUtil.closeSession();
	return otid;
	
}	

/**
 * 新增订单
 * @param order
 * @return
 */
public  Integer addOrder(Order order) {
	Session session = SessionFactoryUtil.getSession();
	Transaction transaction = session.beginTransaction();
	
	Integer oid = (Integer) session.save(order);
	
	transaction.commit();
	SessionFactoryUtil.closeSession();
	return oid;
	
}	
	
/**
 *  查询单个订单 
 * @param order
 * @return
 */
//public Order getOrder(Order order) {
//	Session session = SessionFactoryUtil.getSession();
//	Transaction transaction = session.beginTransaction();
//	
//	Order o = session.get(Order.class, order.getOrderId());
//	
//	transaction.commit();
//	session.close();
//	return o;
//	
//}	
/**
 * 查询单个   默认懒加载      通过字段控制,强制加载。Hibernate.initialize()
 * @param order
 * @return
 */
public Order getOrder(Order order) {
	Session session = SessionFactoryUtil.getSession();
	Transaction transaction = session.beginTransaction();
	
	Order o = session.get(Order.class, order.getOrderId());
	if(o!=null&&new Integer(1).equals(order.getInitorderItems())) {
		Hibernate.initialize(o.getOrderId());//强制加载 立即加载
	}
	transaction.commit();
	SessionFactoryUtil.closeSession();
	return o;
	
}	
/**
 * 查询所有订单
 * @param order
 * @return
 */
public List<Order> getOrderList() {
	Session session = SessionFactoryUtil.getSession();
	Transaction transaction = session.beginTransaction();
	
	List list=session.createQuery("from Order").list();
	
	transaction.commit();
	SessionFactoryUtil.closeSession();
	return list;
	
}

/**
 * 普通删除
 */

public void deleteOrder(Order order) {
	Session session = SessionFactoryUtil.getSession();
    Transaction transaction = session.beginTransaction();
    
    Order o = session.get(Order.class, order.getOrderId());//查询订单
    for (OrderItem ot : o.getOrderItems()) {
    	   session.delete(ot);//删除订单里的订单项
	}
    session.delete(o);//删除订单
    
    transaction.commit();
    SessionFactoryUtil.closeSession();
    

}




	
}

测试类

package com.zking.four.dao;


import java.util.List;

import org.junit.Test;

import com.zking.four.entity.Order;
import com.zking.four.entity.OrderItem;

public class OrderDaoTest {

	private OrderDao orderDao=new OrderDao();
	/**级联新增
	 * 往订单1中新增一个订单项
	 */
	@Test
	public void testAddOrderItem() {
		OrderItem orderItem=new OrderItem();
		Order order=new Order();
		order.setOrderId(1);
		orderItem.setOrder(order);
		orderItem.setProductId(1);
		orderItem.setQuantity(99);
		this.orderDao.addOrderItem(orderItem);
	}
	
	
	/**级联新增
	 *例子 : 提交购物车中含有6个订单项的一个订单
	 *  以前:OrderDao.add
	 *     for(){
	 *       OrderItem.add
	 *    }
	 *    
	 *  现在  :
	 *  
	 */
	@Test
	public void testAddOrder() {
		Order order=new Order();
		order.setOrderNo("3h");
		for (int i = 1; i < 7; i++) {
			OrderItem orderItem=new OrderItem();
			orderItem.setProductId(i);
			orderItem.setQuantity(i);	
			
			orderItem.setOrder(order);//订单项放入到订单
			order.getOrderItems().add(orderItem);//获取订单项集合     往订单 加入订单项
			
		}
		  this.orderDao.addOrder(order);//调用新增订单的方法
	}
	
	
	
//	/**
//	 * 级联查询单个  懒加载
//	 */
//	@Test
//	public void testGetOrder() {
//		Order order=new Order();
//		order.setOrderId(2);
//		Order o = this.orderDao.getOrder(order);
//		System.out.println(o.getOrderNo());//2h 
//		System.out.println(o.getOrderItems().size());//不输出     懒加载获取不到(session 关闭了)
//	}
//	
	/**
	 * 级联查询单个  默认懒加载    order.setInitorderItems(1) 强制加载
	 */
	@Test
	public void testGetOrder() {
		Order order=new Order();
		order.setInitorderItems(1);//强制加载    立即加载
		order.setOrderId(2);
		Order o = this.orderDao.getOrder(order);
		System.out.println(o.getOrderNo());//2h 
		System.out.println(o.getOrderItems().size());//6    立即加载   获取 
	}
	

	
	
	/**
	 * 级联查询所有   默认懒加载
	 */
	@Test
	public void testGetOrderList() {
		List<Order> orderList=this.orderDao.getOrderList();
		for (Order o : orderList) {	
			System.out.println(o.getOrderNo()); 
			System.out.println(o.getOrderItems().size());//  如果立即加载  将执行n+1条sql语句(查询订单1   再单个查询订单项n) 耗性能
		}
		
		}
	
	/**
	 * 普通删除	
	 */
		@Test
		public void testDeleteOrder() {
			Order order=new Order();
			order.setOrderId(2);
			this.orderDao.deleteOrder(order);
		}
		
	
	
	
}

. 案例:菜单对象的一对多双向自关联

hibernate 一对多/多对一 级联新增,查询

实体类

hibernate 一对多/多对一 级联新增,查询

映射文件
hibernate 一对多/多对一 级联新增,查询

dao方法

hibernate 一对多/多对一 级联新增,查询

测试类
hibernate 一对多/多对一 级联新增,查询

结果
hibernate 一对多/多对一 级联新增,查询

. 如何将多方映射成一个有序的集合
bag元素可以映射List集合,order-by属性还可以用来排序(asc升序|desc降序),其它和set元素的使用一样

 <!--order by 填的是表的列字段 -->
   <bag order-by="position" name="children" cascade="save-

update" inverse="true">
     <key column="parent_node_id"></key>
     <one-to-many class="com.zking.five.entity.TreeNode"/><!-- 

描述当前节点与子节点的关系:   一对多   一个节点有多个子节点 -->
   </bag>