• hibernate映射-双向一对多映射


    (当然双向1-n与双向n-1是完全相同的。)

    双向1-n需要在1的一端访问n的一端,同时,n的一端也可以访问1的一端。

    举例:Customer-Order

    一、代码演示:

    {类文件↓}

     Customer:

     1 import java.util.HashSet;
     2 import java.util.Set;
     3 
     4 public class Customer {
     5     
     6     private Integer customerId;
     7     private String customerName;
     8     
     9     
    10     /**
    11      * 1. 此处的集合类型必须要用 接口类型,后面会发现读取orders 的类型是org.hibernate.collection.internal.PersistentSet
    12      *         一个hibernate内置的一个集合类,是set的子类
    13      * 2. 此处需要将集合进行初始化,防止空指针异常
    14      */
    15     private Set<Order> orders = new HashSet<>();
    16     
    17     
    18     public Set<Order> getOrders() {
    19         return orders;
    20     }
    21     public void setOrders(Set<Order> orders) {
    22         this.orders = orders;
    23     }
    24     
    25     
    26     public Integer getCustomerId() {
    27         return customerId;
    28     }
    29     public void setCustomerId(Integer customerId) {
    30         this.customerId = customerId;
    31     }
    32     public String getCustomerName() {
    33         return customerName;
    34     }
    35     public void setCustomerName(String customerName) {
    36         this.customerName = customerName;
    37     }
    38     
    39 }    
    Customer.class

    Order:

     1 public class Order {
     2     
     3     private Integer orderId;
     4     private String orderName;
     5     
     6     private Customer customer;
     7 
     8     public Integer getOrderId() {
     9         return orderId;
    10     }
    11 
    12     public void setOrderId(Integer orderId) {
    13         this.orderId = orderId;
    14     }
    15 
    16     public String getOrderName() {
    17         return orderName;
    18     }
    19 
    20     public void setOrderName(String orderName) {
    21         this.orderName = orderName;
    22     }
    23 
    24     public Customer getCustomer() {
    25         return customer;
    26     }
    27 
    28     public void setCustomer(Customer customer) {
    29         this.customer = customer;
    30     }
    31     
    32 }
    Order.class

     {映射文件↓}

    hbm.xml配置文件中,并没有相应的<one-to-many>属性,而是用<set>来代替,而<set>的子元素中,有<one-to-many>子元素

    Customer.hbm.xml:

     1 <?xml version="1.0"?>
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
     4 <!-- Generated 2015-11-29 10:18:07 by Hibernate Tools 3.4.0.CR1 -->
     5 <hibernate-mapping package="com.zit.hibernate.n21.both">
     6     <class name="Customer" table="CUSTOMERS">
     7         <id name="customerId" type="java.lang.Integer">
     8             <column name="CUSTOMER_ID" />
     9             <generator class="native" />
    10         </id>
    11         <property name="customerName" type="java.lang.String">
    12             <column name="CUSTOMER_NAME" />
    13         </property>
    14         
    15         <!-- 映射1 对多的那个集合属性 -->
    16         <set name="orders" table="ORDERS" inverse="true" cascade="delete">
    17             <key column="CUSTOMER_ID"></key>
    18             <one-to-many class="Order"/>
    19         </set>
    20         
    21     </class>
    22 </hibernate-mapping>
    Customer.hbm.xml

    注意:

    1 <set name="orders" table="ORDERS" inverse="true" cascade="delete">
    2     <key column="CUSTOMER_ID"></key>
    3     <one-to-many class="Order"/>
    4 </set>

    <set>  name是1的一端的包含的n的一端的属性名;table=“”是表名,参照的是ORDERS表,得跟Orders.hbm.xml中的那个表名一致。

    <key> 子元素中的column=“”要与  Orders.hbm.xml 中的 <many-to-one>中的<column/>对应一致。

    (务必注意这两个一一对应关系)

    <one-to-many> 对应n的一端的类全类名。要指明是one-to-many类型,因为many-to-many也是用set来表示的。

    Order.hbm.xml

     1 <?xml version="1.0"?>
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
     4 <!-- Generated 2015-11-29 10:18:07 by Hibernate Tools 3.4.0.CR1 -->
     5 <hibernate-mapping package="com.zit.hibernate.n21.both">
     6     <class name="Order" table="ORDERS">
     7         <id name="orderId" type="java.lang.Integer">
     8             <column name="ORDER_ID" />
     9             <generator class="native" />
    10         </id>
    11         <property name="orderName" type="java.lang.String">
    12             <column name="ORDER_NAME" />
    13         </property>
    14         <many-to-one name="customer" class="Customer">
    15             <column name="CUSTOMER_ID" />
    16         </many-to-one>
    17     </class>
    18 </hibernate-mapping>
    Order.hbm.xml

    二、使用注意:

    1.插入数据时:

       先保存1的一端的数据,再保存多的一端的数据,若反之,则会多出UPDATE语句。(此处会多出的UPDATE是在单向n- 1中,会多的UPDATE语句数量的两倍,因为双向1-n两边都会维护关联关系)

       但是这种双向关联,在插入时,会有UPDATE语句产生,这与单向的n-1不同,在单向的n-1关联关系中,若用户先插入1的一端,再插入n的一端,是不会出现UPDATE语句的。在双向1-n关联关系中,若先插入1的一端,再插入多的一端,UPDATE会相应少,数目为插入的多的一端的数据数目。反之,若先插入n的一端,再插入1的一端,则UPDATE语句数目会是前者的两倍。

    [双方都维护关联关系,会降低程序效率。可以通过设置 inverse 属性来决定是由双向关联中的哪一方来维护表和表之间的关联关系。inverse = false 的为主动方,inverse=true的为被动方。若未设置inverse=true,则双方都维护。

     在1-n关系中,将n方设置为主控方将有助于性能改善,见Customer.hbm.xml中的设置]

      session.save(object);

    2.在Customer.class中,需要将set<Order>进行初始化,即:

      Set<Order> orders = new HashSet<>();

      否则会出现空指针异常。

    3.延迟加载:

       在获取了Customer的对象后,customer.getOrders().getClass()返回的是一个hibernate内置的

       集合类型:PersistentSet,该类型具有延迟加载和存放代理对象的功能。是Java.Util.Set接口的一个实现类。

       这也表明了在声明定义几何属性时必须把属性声明为Java接口类型,如Set,而不能是HashSet

    4.懒加载异常:LazyInitializationException

    5.在需要使用集合中元素的时候才进行初始化,而使用集合的size()的时候都不会进行初始化。

    6.<set>中配置 order-by,让集合内的元素按指定的属性,升序、降序排列,

       例:<set order-by="ORDER_NAME DESC">

       注意:这里使用的是表中的字段名,而不是持久化类的属性名。

  • 相关阅读:
    Nodejs学习笔记(三)--- 模块
    Nodejs学习笔记(二)--- 事件模块
    Nodejs学习笔记(一)--- 简介及安装Node.js开发环境
    leetcode题解实践
    坑爹的bugsbunnyctf复现
    两道interesting的题目
    python 习题集
    数据结构与算法--java描述
    pentestbox下运行ssh报错,命令报错
    ntfs交换数据流在隐写
  • 原文地址:https://www.cnblogs.com/zitt/p/5073524.html
Copyright © 2020-2023  润新知