Hibernate一对多关联关系

什么是关联关系:
首先我们要了解的是什么是关联关系:
1.1 关联指的是类之间的引用关系。
如果类A与类B关联,那么被引用的类B将被定义为类A的属性
例如:

  class B{private String name;}public class A{private B b = new B;public A(){}}

关联的分类:关联可以分为一对一、一对多/多对一、多对多关联(常见的就是订单与订单项)
关联是有方向的
Hibernate实现订单与订单项的一对多的增删改查:
首先准备好实体类,Order和OrderItem
Order(订单表):

package com.lihao.three.entity;import java.util.ArrayList;
import java.util.List;public class Order {private Integer orderId;private String orderNo;//建立了关联关系   一个订单对应着多个订单项private List<OrderItem> orderItems = new ArrayList<>();private Integer initChildren = 0;//0是懒加载   1是falsepublic Integer getInitChildren() {return initChildren;}public void setInitChildren(Integer initChildren) {this.initChildren = initChildren;}public List<OrderItem> getOrderItems() {return orderItems;}public void setOrderItems(List<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;}@Overridepublic String toString() {return "Order [orderId=" + orderId + ", orderNo=" + orderNo + "]";}}

OrderItem(订单项表):

package com.lihao.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;}@Overridepublic String toString() {return "OrderItem [orderItemId=" + orderItemId + ", productId=" + productId + ", quantity=" + quantity+ ", oid=" + oid + "]";}}

然后配置映射文件:Order.hbm.xml配置好关联关系的列和在OrderItem.hbm.xml中配置好实体类映射和对应的列
首先我们先来配置Order.hbm.xml
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.lihao.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 lazy="true" name="orderItems" cascade="save-update" inverse="true"><!-- 从表的外键 --><key column="oid"></key><one-to-many class="com.lihao.three.entity.OrderItem"/></bag></class></hibernate-mapping>

然后我们来配置OrderItem.hbm.xml:
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.lihao.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><property name="oid" type="java.lang.Integer" column="oid" insert="false" update="false"></property><many-to-one name="order" class="com.lihao.three.entity.Order" column="oid"></many-to-one></class>
</hibernate-mapping>

然后在核心配置文件hibernate.cfg.xml中配置映射文件:

<!-- 一对多 --><mapping resource="com/lihao/three/entity/OrderItem.hbm.xml"/><mapping resource="com/lihao/three/entity/Order.hbm.xml"/>

然后就建立dao层写demodao类的增删查改
DemoDao:

package com.lihao.three.dao;import java.util.List;import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;import com.lihao.three.entity.Order;
import com.lihao.three.entity.OrderItem;
import com.lihao.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.getOrderItems());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.getOrderItems()) {session.delete(oi);}session.delete(order2);
//      session.delete(order);transaction.commit();session.close();}
}

写完dao方法我们需要检验它的正确性:
我们就需要选中你的DemoDao这个类然后CTRL+N在输入框中输入(junit)建立DemoDao的测试类—>DemoDaoTest
然后我们就要在DemoDaoTest中写测试代码了:

package com.lihao.three.dao;import java.util.List;import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;import com.lihao.three.entity.Order;
import com.lihao.three.entity.OrderItem;
import com.lihao.two.util.SessionFactoryUtils;/*** @Before每测试一个@test标记的测试方法,都会在调用之前执行一次* @After每测试一个@test标记的测试方法,都会在调用之后执行一次* @author 李浩**/
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("释放资源的");
//  }@Testpublic void testAddOrder() {Order order = new Order();order.setOrderNo("p20");OrderItem orderItem = null;for (int i = 0; i <6; i++) {orderItem = new OrderItem();orderItem.setProductId(10+i);orderItem.setQuantity(20+i);
//          维护关联关系orderItem.setOrder(order);order.getOrderItems().add(orderItem);}demoDao.addOrder(order);}@Testpublic void testAddOrderItem() {OrderItem orderItem = null;for (int i = 0; i <6; i++) {orderItem = new OrderItem();orderItem.setProductId(12+i);orderItem.setQuantity(31+i);Order order = new Order();order.setOrderId(1);order.getOrderItems().add(orderItem);orderItem.setOrder(order);demoDao.addOrderItem(orderItem);}}@Testpublic 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.wt.three.entity.Order.orderItems,
//      could not initialize proxy - no Session
//      原因:操作了两次数据库:当lazy=false的时候,会让hibernate执行完两次操作session才会关闭
//      当lazy=false的时候,会让hibernate执行完一次操作session才会关闭
//      从上面看:当lazy=false更好;但是为什么hibernate默认让它等于true
//      处于性能的考虑,所以hibernate3.0出现lazy这个属性,并让他默认等于true,也就是说比加载关联属性List<OrderItem> orderItems = o.getOrderItems();for (OrderItem orderItem : orderItems) {System.out.println(orderItem);}System.out.println(o);}@Testpublic void testGetOrderList() {List<Order> orderList = this.demoDao.getOrderList();for (Order order : orderList) {for (OrderItem orderItem : order.getOrderItems()) {System.out.println(orderItem);}System.out.println(order);}}@Testpublic void testDelOrder() {Order order = new Order();order.setOrderId(1);this.demoDao.delOrder(order);}}
然后Hibernate实现订单与订单项的一对多的增删改查就完成了

刚刚在配置order.hbm.xml文件的时候提到了懒汉模式,下面我就向大家简单说说懒汉模式
说到懒汉模式,那我就不得不在简单的提提饿汉模式和单例模式,好啦废话不多说,进入正文。
首先什么是单例模式呢?
我个人的理解就是当用这个类的对象的时候就只能创建同一个对象。
而在单例模式中又经常是懒汉和恶汉式进行加载
注意:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
简单来说就是一个班级只能有一个班主任。
接下来是什么是饿汉模式:
简单来说就是很饥饿,你想想,当人很饥饿时候是不是就有什么吃什么,那就是这个道理,所以就已加载类就创建对象
饿汉模式:

public class Hungery{private static Hungery demo;//一个静态变量private Hungery(){//私有的构造方法,保证不能外面new对象}static{//静态块demo= new Hungery();}public static Hungery getDemo(){//静态方法retrn demo;}
}

这就是饿汉模式。但是这个有一个问题,是什么呢?
那就是如果我只想要这个类的一个静态方法,那么当我在调用这个静态方法时,
这个对象也就被创建了,那么这无疑是耗费内存的。
就好比我给别人介绍一个房子,说这房子怎么样,厨房排风系统很好。
这时主人突然就跑了出来,快买快买。这就尴尬了。就好比这个冷笑话。
最后是简单介绍一下懒汉模式:
懒汉模式就是用的时候再去加载。就好比刚才房子的中介介绍了房子的各种好,客人终于动心了就想买,这时候房子主人才出来和客人进行下一步的沟通。好我们继续看代码:
懒汉模式:

public class  Hungery{private static Hungery demo2;//一个静态变量private Hungery(){//私有的构造方法,保证不能外面new对象}public static Hungery getDemo2(){//静态方法if(null==demo2){synchronized (Hungery.class){//每次都要判断if(null==demo2){demo2 = new Hungery();}}}retrn demo2;}
}

这就是懒汉模式,这个由于没有静态块那么就不会再类加载时就创建对象。只有调用这个方法时候才创建对象,而且需要判断,就好比客人说接下来就和主人谈吧,主人说谈过了就和以前那个谈。没谈过我现在就出来(这个例子是呼应那个判断。感觉有点欠火候)总觉得判断有点不够简洁,不仅有人要说了:就你事多!不判断哪知道要不要创建对象。

那么有没有既能可以调用其他方法不创建对象,又能创建对象不需要判断 就是同时修改了饿汉和懒汉的缺点的。有的!请看:

public class  Hungery{private Hungery(){//私有的构造方法,保证不能外面new对象}public static class HungeryDemo(){//静态方法public static class getDemo3(){private static class Hungery demo3 = new Hungery();}public static Hungery getOtherMethods(){return getDemo3.demo3;} public static void otherMethods(){System.out.println("*******调用其它方法不会创建对象**********");}}
}

总结:
hibernate框架一对多的执行原理:

hibernate框架一对多的执行原理:1、对hibernate.cfg.xml进行建模,等到sessionfactory对象2、并且拿到mapping   resource里的内容3、拿到了Order.hbm.xml配置文件4、可以再次建模,拿到了com.lihao.three.entity.Order,以及t_hibernate_order类属性、以及表列段5、生成动态的sql:select orderId,orderNo from t_hibernate_order;执行sql最终得到meterDta源数据模型orderId,orderNo1        p15         p67        p78        p101........6、Class.forName("com.lihao.three.entity.Order");o1.setOrderId(1);o1.setOrderNo(P1)........最终list中所有的order实例都有值了;(这里只是处理表面的非外键列段,原理完全跟baseDao一样)7、处理关联关系:orderItems  oid com.lihao.three.entity.OrderItem通过one-to-many这个标签以及class对应的全路径名会找对class对应的全路径名对应的专属映射文件也就是找到了Orderitem.hbm.xml这个文件,找到它之后就可以拿到t_hibernate_order_item8、select * from t_hibernate_order_item;最终的到了一个List<OrderItem> orderItems      9、给order的关联关系属性赋值List<Order> list = new ArrayList<>();for(Order o : list){o.setOrderItems(orderItems);}

Hibernate一对多关联关系相关推荐

  1. (转)Hibernate框架基础——一对多关联关系映射

    http://blog.csdn.net/yerenyuan_pku/article/details/52746413 上一篇文章Hibernate框架基础--映射集合属性详细讲解的是值类型的集合(即 ...

  2. (八)Hibernate的一对多关联关系

    一.概述 例如,以客户(Customer)和订单(Order)为例,一个客户能有多个订单,一个订单只能有一个客户. 从Customer到Order是一对多关联,在java类中的面向对象设计应该一个Cu ...

  3. Hibernate一对多单向关联和双向关联映射方法及其优缺点

    一对多关联映射和多对一关联映射实现的基本原理都是一样的,既是在多的一端加入一个外键指向一的一端外键,而主要的区别就是维护端不同. 它们的区别在于维护的关系不同: 一对多关联映射是指在加载一的一端数据的 ...

  4. Hibernate - 单向一对多关联关系映射

    上篇博文描述了Hibernate - 单向多对一关联关系映射,本篇博文继续学习单向一对多关系映射. 这里Customer:Order= 1:N,外键保存在Order表中. [1]修改Customer和 ...

  5. Hibernate中双向一对多关联关系

    前边我们讲过了单向多对一的关联关系,即在Java代码-hbm.xml配置文件-数据库表格中只是描述了一种类中多个对象可以对应一个其他类对象的关联关系.我们需要在一个类中含有另一个类的引用变量,然后在包 ...

  6. Hibernate的一对多关联关系(单向和双向)

    在领域模型中,类与类之间最普遍的关系就是关联关系.在 UML 中,关联是有方向的.以 Customer 和 Order 为例:一个用户能发出多个订单, 而一个订单只能属于一个客户.从 Order 到 ...

  7. hibernate 的一对多关联关系映射配置

    hibernate 是操作实体类: 表是一对多的关系,当创建这2个实体的时候 在一的一方定义一个多的一方的集合 在多的一方定义一个一的一方的对象 表是多对多的关系,当创建这2个实体的时候 在互相中都有 ...

  8. Hibernate学习4—关联关系一对多映射2

    第四节:班级学生一对多映射实现(双向) 查询班级的时候能够获取所有的学生: 在上一节的基础之上:我们在Class端也保存学生的关系: com.cy.model.Class: public class ...

  9. hibernate 一对多(one-to-many)双向关联

    一对多(one-to-many)双向关联实例(Department- Employee) 这里的一对多双向关联是在域模型(实体对象模型)上的概念,在关系数据库中,只存在外键参照关系,而且总是由&quo ...

  10. hibernate一对多关联映射

    一对多关联映射 映射原理 一对多关联映射和多对一关联映射的映射原理是一致的,都是在多的一端加入一个外键,指向一的一端.关联关系都是由多端维护,只是在写映射时发生了变化. 多对一和一对多的区别 多对一和 ...

最新文章

  1. HTML5 Web app开发工具Kendo UI Web中图像浏览器的使用
  2. P4166 [SCOI2007]最大土地面积
  3. 剑指offer-链表中倒数第K个结点
  4. python读取图片上的文字_Python帮你读取图片中的文字(OCR)
  5. Django框架——中间件
  6. 【bzoj 十连测】[noip2016十连测第三场]Problem C: 序列(静态主席树)
  7. css线条伸缩_CSS3弹性伸缩布局(一)——box布局
  8. 使用ffmpeg破解m3u8加密视频文件
  9. docker安装solr搜索引擎
  10. java string 加法_java 对String 加法计算
  11. ARL资产灯塔收集系统
  12. promise是什么及其用法
  13. ping是什么,有什么作用?
  14. 腾讯云迁移到私有云记录
  15. SCU(System Control Units)
  16. 无源测向技术介绍——振幅法测向
  17. Android获取微信聊天记录的过程详解
  18. 光伏制氢电力成本有望降到一毛五,为光伏发电彻底解决储能难题!
  19. OutLook中发送用户密码加密的小技巧
  20. 渔网-刺网-三层刺网:三层刺网

热门文章

  1. 样本峰度(kurtosis)与随机变量的峰度及四阶统计量之间的关系和计算估计
  2. 百数巡检领域系统能力展示
  3. win10系统迁移后系统重装_win10分区助手迁移系统到SSD固态硬盘的技巧
  4. 7.5.1 拓补排序(有向图)
  5. sncr脱硝技术流程图_脱硝技术介绍(SCR和SNCR)
  6. upd协议java收发消息小练习
  7. tensorflow(gpu) win10安装 1060显卡驱动
  8. 做网站的定律原理和效应
  9. 微信小程序入门--注册账号
  10. 测试思维:正向思维和逆向思维