hibernate 一对多/多对一 级联新增,查询
1. 什么是关联(association)
关联指的是类之间的引用关系。如果类A与类B关联,那么被引用的类B将被定义为类A的属性。例如:
public class A{
private B b = new B;
public A(){}
}
2.关联的分类:关联可以分为一对一、一对多/多对一、多对多关联
关联是有方向的
#关键点都在数据库中的外键上面
3案例 .如何建立订单项和订单一对多双向关联
1 定义实体及映射文件
Order
OrderItem
映射类
Order.hbml.xml
OrderItem.hbml.xml
注意:在Hibernate当中定义实体对象的集合属性时,只能使用接口而不能使用类
2 建立订单到订单项的一对多关联关系 Order.hbml.xml
3 建立订单项到订单的多对一关联关系 OrderItem.hbml.xml
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);
}
}
. 案例:菜单对象的一对多双向自关联
表
实体类
映射文件
dao方法
测试类
结果
. 如何将多方映射成一个有序的集合
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>