`

精通Hibernate——映射一对多关联关系

阅读更多

在域模型(实体域)中,关联关系是类与类之间最普遍的关系。根据UML语言,关系是有方向的。下面以客户(Customer)和订单(Order)的关系为例,阐述一下ORM的中的一对多映射:
我们知道,在关系数据库中,只存在外键参照关系,而且总是由“many”方参照“one“方。
1.建立多对一单向关联——Order(many)--->Customer(one):
-------------------------------Order.java--------------------------------

pack mypack;
import java.io.Serializable;
public class Order implements Serializable{
   
private int id;
   
private String orderNumber;
   
private Customer customer;
   
   
//构造方法及set方法get方法
   
}

在以上代码中customer属性要使用<many-to-one>来映射:
多对一单向关联(many方)

<many-to-one>
    name 
= "customer"   --待映射的持久化类属性名
    column 
= "customer_Id"  --数据库外键字段
    
class = "mypack.Customer"  --持久化类
    not
-null = "true"/>

a.  <many-to-one>的not-null属性 
not-null属性会影响Hiberntae的运行时行为,Hibernate在保存Order对象时,会先检查它的customer属性是否为null:
若为null:在执行session.save(Order)时会抛出PropertyValueException异常;
原因很简单:既然Customer为null,那么对应的外键Customer_Id也为null,试问外键都没有,Order表的数据能插得进去吗
若将not-null 属性设为false:表示外键引用可以为null,试想一下,数据库数据可以插进去吗?
我们来看:在执行session.save(Order)时,发出了sql语句:insert into......
但是当Hibernate自动清理(flush)缓存时,抛出新的异常:TransientObjectException
所谓清理是提交事务或手动Flush,将session与数据库保持同步,很显然不可能同步嘛,Order对象虽然持久化,但Customer没有.
    注:是否应该把<many-to-one>的not-null属性设为true,这根据实际业务而定。通常,订单总是由客户自己发出,因此建议设为true.
b.  级联保存与更新
默认情况下,Hibernate持久化一个对象,不会自动持久化所关联的其它临时对象,因此会有TransientObjectException,
想它关联也可以,<many-to-one>中加个属性cascade="save-update"即可.

2.建立一对多关联——Customer(one)--->Order(many):
-----------------------------Customer.java-------------------------------

package mypack;
import 
public calss Customer implements Serlizliab;e{
    
private int id;
    
private String name;
    
private Set orders = new HsahSet();

    
//构造方法及set方法get方法
}

一对多关联(one方)

<set 
      name 
= "orders"  --持久化对象的属性
      cascade 
= "save-update" --级联操作
      
<key cloumn = "customer_Id"/> --外键
      
<one-to-many class = "mypack.Order"/> --持久化类
</set>

a.  <set>元素的inverse属性
  在映射一对多的双向关联时,应该在“one”方把inverse属性设为true,这样可提高应用性能。
                    inverse:控制反转,为true表示反转,由它方负责;反之,不反转,自己负责;
                    如果不设,one和many两方都要负责控制,因此,会引发重复的sql语句以及重复添加数据,
        在建立两个象的双向关系时,应该同时修改关联两端的对象属性:
                    customer.getOrders().add(order);
                    order.setCustomer(customer);

        这样做可提高业务逻辑的独立性,使业务逻辑的程序代码不受Hibernate实现的影响。同理解除双向关系也一样。
b.  级联删除(从数据库删除相关表记录)
         当删除Customer对象时,及联删除Order对象.只需将cascad属性设为delete即可.
          注:删除后的对象,依然存在于内存中,只不过由持久化态变为临时态.
c.  父子关系(逻辑删除,只是解除了关联关系)
         自动删除不再和Customer对象关联的Order对象.只需将cascade属性设为delete-orphan.
                     customer.getOrders().remove(order);
                     order.setCustomer(null);
          注:当关联双方都存在父子关系,就可以把父方的cascade属性设为delete-orphan,所谓父子关系,是由父方来控制子方的生命周期.

在域模型(实体域)中,关联关系是类与类之间最普遍的关系。根据UML语言,关系是有方向的。下面以客户(Customer)和订单(Order)的关系为例,阐述一下ORM的中的一对多映射:
我们知道,在关系数据库中,只存在外键参照关系,而且总是由“many”方参照“one“方。
1.建立多对一单向关联——Order(many)--->Customer(one):
-------------------------------Order.java--------------------------------

pack mypack;
import java.io.Serializable;
public class Order implements Serializable{
   
private int id;
   
private String orderNumber;
   
private Customer customer;
   
   
//构造方法及set方法get方法
   
}

在以上代码中customer属性要使用<many-to-one>来映射:
多对一单向关联(many方)

<many-to-one>
    name 
= "customer"   --待映射的持久化类属性名
    column 
= "customer_Id"  --数据库外键字段
    
class = "mypack.Customer"  --持久化类
    not
-null = "true"/>

a.  <many-to-one>的not-null属性 
not-null属性会影响Hiberntae的运行时行为,Hibernate在保存Order对象时,会先检查它的customer属性是否为null:
若为null:在执行session.save(Order)时会抛出PropertyValueException异常;
原因很简单:既然Customer为null,那么对应的外键Customer_Id也为null,试问外键都没有,Order表的数据能插得进去吗
若将not-null 属性设为false:表示外键引用可以为null,试想一下,数据库数据可以插进去吗?
我们来看:在执行session.save(Order)时,发出了sql语句:insert into......
但是当Hibernate自动清理(flush)缓存时,抛出新的异常:TransientObjectException
所谓清理是提交事务或手动Flush,将session与数据库保持同步,很显然不可能同步嘛,Order对象虽然持久化,但Customer没有.
    注:是否应该把<many-to-one>的not-null属性设为true,这根据实际业务而定。通常,订单总是由客户自己发出,因此建议设为true.
b.  级联保存与更新
默认情况下,Hibernate持久化一个对象,不会自动持久化所关联的其它临时对象,因此会有TransientObjectException,
想它关联也可以,<many-to-one>中加个属性cascade="save-update"即可.

2.建立一对多关联——Customer(one)--->Order(many):
-----------------------------Customer.java-------------------------------

package mypack;
import 
public calss Customer implements Serlizliab;e{
    
private int id;
    
private String name;
    
private Set orders = new HsahSet();

    
//构造方法及set方法get方法
}
一对多关联(one方)
<set 
      name 
= "orders"  --持久化对象的属性
      cascade 
= "save-update" --级联操作
      
<key cloumn = "customer_Id"/> --外键
      
<one-to-many class = "mypack.Order"/> --持久化类
</set>
a.  <set>元素的inverse属性
  在映射一对多的双向关联时,应该在“one”方把inverse属性设为true,这样可提高应用性能。
                    inverse:控制反转,为true表示反转,由它方负责;反之,不反转,自己负责;
                    如果不设,one和many两方都要负责控制,因此,会引发重复的sql语句以及重复添加数据,
        在建立两个象的双向关系时,应该同时修改关联两端的对象属性:
                    customer.getOrders().add(order);
                    order.setCustomer(customer);

        这样做可提高业务逻辑的独立性,使业务逻辑的程序代码不受Hibernate实现的影响。同理解除双向关系也一样。
b.  级联删除(从数据库删除相关表记录)
         当删除Customer对象时,及联删除Order对象.只需将cascad属性设为delete即可.
          注:删除后的对象,依然存在于内存中,只不过由持久化态变为临时态.
c.  父子关系(逻辑删除,只是解除了关联关系)
         自动删除不再和Customer对象关联的Order对象.只需将cascade属性设为delete-orphan.
                     customer.getOrders().remove(order);
                     order.setCustomer(null);
          注:当关联双方都存在父子关系,就可以把父方的cascade属性设为delete-orphan,所谓父子关系,是由父方来控制子方的生命周期.
                     

在域模型(实体域)中,关联关系是类与类之间最普遍的关系。根据UML语言,关系是有方向的。下面以客户(Customer)和订单(Order)的关系为例,阐述一下ORM的中的一对多映射:
我们知道,在关系数据库中,只存在外键参照关系,而且总是由“many”方参照“one“方。
1.建立多对一单向关联——Order(many)--->Customer(one):
-------------------------------Order.java--------------------------------

pack mypack;
import java.io.Serializable;
public class Order implements Serializable{
   
private int id;
   
private String orderNumber;
   
private Customer customer;
   
   
//构造方法及set方法get方法
   
}
在以上代码中customer属性要使用<many-to-one>来映射:
多对一单向关联(many方)
<many-to-one>
    name 
= "customer"   --待映射的持久化类属性名
    column 
= "customer_Id"  --数据库外键字段
    
class = "mypack.Customer"  --持久化类
    not
-null = "true"/>
a.  <many-to-one>的not-null属性 
not-null属性会影响Hiberntae的运行时行为,Hibernate在保存Order对象时,会先检查它的customer属性是否为null:
若为null:在执行session.save(Order)时会抛出PropertyValueException异常;
原因很简单:既然Customer为null,那么对应的外键Customer_Id也为null,试问外键都没有,Order表的数据能插得进去吗
若将not-null 属性设为false:表示外键引用可以为null,试想一下,数据库数据可以插进去吗?
我们来看:在执行session.save(Order)时,发出了sql语句:insert into......
但是当Hibernate自动清理(flush)缓存时,抛出新的异常:TransientObjectException
所谓清理是提交事务或手动Flush,将session与数据库保持同步,很显然不可能同步嘛,Order对象虽然持久化,但Customer没有.
    注:是否应该把<many-to-one>的not-null属性设为true,这根据实际业务而定。通常,订单总是由客户自己发出,因此建议设为true.
b.  级联保存与更新
默认情况下,Hibernate持久化一个对象,不会自动持久化所关联的其它临时对象,因此会有TransientObjectException,
想它关联也可以,<many-to-one>中加个属性cascade="save-update"即可.

2.建立一对多关联——Customer(one)--->Order(many):
-----------------------------Customer.java-------------------------------
package mypack;
import 
public calss Customer implements Serlizliab;e{
    
private int id;
    
private String name;
    
private Set orders = new HsahSet();

    
//构造方法及set方法get方法
}
一对多关联(one方)
<set 
      name 
= "orders"  --持久化对象的属性
      cascade 
= "save-update" --级联操作
      
<key cloumn = "customer_Id"/> --外键
      
<one-to-many class = "mypack.Order"/> --持久化类
</set>
a.  <set>元素的inverse属性
  在映射一对多的双向关联时,应该在“one”方把inverse属性设为true,这样可提高应用性能。
                    inverse:控制反转,为true表示反转,由它方负责;反之,不反转,自己负责;
                    如果不设,one和many两方都要负责控制,因此,会引发重复的sql语句以及重复添加数据,
        在建立两个象的双向关系时,应该同时修改关联两端的对象属性:
                    customer.getOrders().add(order);
                    order.setCustomer(customer);

        这样做可提高业务逻辑的独立性,使业务逻辑的程序代码不受Hibernate实现的影响。同理解除双向关系也一样。
b.  级联删除(从数据库删除相关表记录)
         当删除Customer对象时,及联删除Order对象.只需将cascad属性设为delete即可.
          注:删除后的对象,依然存在于内存中,只不过由持久化态变为临时态.
c.  父子关系(逻辑删除,只是解除了关联关系)
         自动删除不再和Customer对象关联的Order对象.只需将cascade属性设为delete-orphan.
                     customer.getOrders().remove(order);
                     order.setCustomer(null);
          注:当关联双方都存在父子关系,就可以把父方的cascade属性设为delete-orphan,所谓父子关系,是由父方来控制子方的生命周期.
                     

 

分享到:
评论

相关推荐

    孙卫琴.精通Hibernate

    此外,还将介绍如何设计和实现实体类,以及如何建立对象之间的关联,如一对一、一对多、多对多关系。 在持久化操作方面,孙卫琴会带领读者学习如何使用Hibernate进行增删改查(CRUD)操作,包括对象的保存、更新、...

    精通hibernate

    6. **关联映射**:Hibernate支持一对一、一对多、多对一和多对多的关联映射。`@OneToOne`、`@OneToMany`、`@ManyToOne`和`@ManyToMany`注解分别用于标记这些关联关系。 7. **懒加载与立即加载**:Hibernate支持懒...

    精通Hibernate

    在Hibernate中,实体类代表数据库表,实体之间的关系(一对一、一对多、多对多)可以通过关联映射实现。例如,使用@OneToOne、@OneToMany、@ManyToOne、@ManyToMany注解来定义不同类型的关联。 五、持久化操作 持久...

    精通Java EE Eclipse Struts2 Hibernate Spring整合应用案例 源代码18章 bookstore

    Hibernate通过映射机制将Java类与数据库表关联,简化了数据存取操作,并提供了事务管理、缓存策略等功能。 Spring框架是Java EE领域的重要组件,以其IoC(Inversion of Control)容器和AOP(Aspect-Oriented ...

    最经典的hibernate教程_从入门到精通

    在高级主题中,我们将涉及一对多、多对一、一对一和多对多的关系映射,以及懒加载和即时加载策略。例如,@OneToMany、@ManyToOne、@OneToOne和@ManyToMany注解分别用于定义这些关联关系。懒加载意味着关联的对象只在...

    最经典的hibernate教程_从入门到精通_第四篇

    7. **实体关联映射**:研究一对一、一对多、多对一、多对多等各种关联映射的配置和使用,包括@OneToOne、@OneToMany、@ManyToOne、@ManyToMany等注解。 8. **缓存机制**:学习Hibernate的缓存策略,包括一级缓存...

    hibernate入门

    了解了基本概念后,可以深入研究Hibernate的高级特性,如一对多、多对一、一对一和多对多的关联映射,级联操作,延迟加载,缓存机制,以及HQL(Hibernate Query Language)和Criteria API等。 总结,Hibernate通过...

    最的hibernate教程从入门到精通第4篇共四篇PPT学习教案.pptx

    在 Hibernate 配置中,需要定义这两个类与数据库表之间的映射关系,特别是 OrderLine 中的 order 属性,它与 Order 类形成了一对多的关联。 预习问题提到了 Hibernate 支持的两种查询方式:HQL 和 SQL。HQL 是 ...

    hibernat培训

    4. **关联问题**:管理对象之间的多对一、一对多和多对多关系。 5. **导航问题**:在对象之间建立导航机制以实现对象结构的动态访问。 O/R Mapping的不匹配会导致额外的工作量,比如手工实现对象与关系的映射,甚至...

    精华api集合 外加教程

    文档"第16章 Hibernate关联映射.doc"可能详细讲解了Hibernate中如何处理对象间的关联,如一对一、一对多、多对一和多对多的映射关系。而"PointCut.doc"可能涉及到Spring AOP中的切点概念,这是定义通知(Advice)...

Global site tag (gtag.js) - Google Analytics