广告
返回顶部
首页 > 资讯 > 精选 >Hibernate映射一对多关联关系是什么
  • 401
分享到

Hibernate映射一对多关联关系是什么

2023-06-17 11:06:44 401人浏览 八月长安
摘要

这篇文章主要讲解了“Hibernate映射一对多关联关系是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Hibernate映射一对多关联关系是什么”吧!在域模型中,类和类之间最普通的关系

这篇文章主要讲解了“Hibernate映射一对多关联关系是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Hibernate映射一对多关联关系是什么”吧!

在域模型中,类和类之间最普通的关系就是关联关系。在UML语言中,关联是有方向的。以客户(Customer)和订单(Order)的关系为例,一个客户可以发出多个订单,而一个订单只能属于一个客户。

从Order到Customer的关联是多对一关联,这意味着每个Order对象都会引用一个Customer对象,因此在Order类中应该定义一个Customer类型的属性,来引用所关联的Customer对象。

从Customer到Order的关联是一对多的关联,这意味着每个Customer对象都会引用一组Order对象,因此在Customer类中应该定义一个集合类型的属性,来引用所有关联的Order对象。

Hibernate映射一对多关联关系是什么

一、建立多对一的单向关联关系

如上例中,我们只需在Order类中定义一个customer属性,而在Customer类中无需定义存放Order对象的集合属性。

Order.java

package mypack;   public class Order  implements java.io.Serializable {       private long id;       private String orderNumber;       private Customer customer;//定义一个Customer属性       public Order() {      }       public Order(Customer customer) {          this.customer = customer;      }      public Order(String orderNumber, Customer customer) {         this.orderNumber = orderNumber;         this.customer = customer;      }          //省略了id,orderNumber的构造方法      public Customer getCustomer() {          return this.customer;      }            public void setCustomer(Customer customer) {          this.customer = customer;      }   }

Customer类的所有属性都是和CUSTOMERS表中的字段一一对应,因此可以直接使用如下的映射代码:

<class name="mypack.Customer" table="CUSTOMERS" >     <id name="id" type="long" column="ID">       <generator class="increment"/>     </id>      <property name="name" type="string" >         <column name="NAME" length="15" />     </property>          </class>

Order类的orderNumber属性和ORDERS表中ORDER_NUMBER字段对应,映射代码和上面类似,此处省去。我们关注的主要地方是,Order类中的customer属性,因为他是Customer类型的,是与ORDERS表的外键CUSTOMER_ID对应的,它的真实值是存在CUSTOMERS表中而ORDERS表存的只是对它的引用,因此customer的映射方法不能如上面一样。

<many-to-one          name="customer"         column="CUSTOMER_ID"         class="mypack.Customer"         not-null="true"           lazy="false" />

使用方法のBussiness.java演示:

package mypack;   import org.hibernate.*;  import org.hibernate.cfg.Configuration;  import java.util.*;   public class BusinessService{    public static SessionFactory sessionFactory;    static{       try{        // 初始化         Configuration config = new Configuration();         config.configure();         sessionFactory = config.buildSessionFactory();      }catch(RuntimeException e){e.printStackTrace();throw e;}    }     public List findOrdersByCustomer(Customer customer){      Session session = sessionFactory.openSession();      Transaction tx = null;      try {        tx = session.beginTransaction();         List orders=session.createQuery("from Order as o where o.customer.id="+customer.getId())                           .list();        //Hibernate执行:select * from ORDERS where CUSTOMER_ID=customer.getId();        tx.commit();        return orders;      }catch (RuntimeException e) {        if (tx != null) {          tx.rollback();        }        throw e;      } finally {        session.close();      }    }     public Customer findCustomer(long customer_id){      Session session = sessionFactory.openSession();      Transaction tx = null;      try {        tx = session.beginTransaction();        Customer customer=(Customer)session.get(Customer.class,new Long(customer_id));        tx.commit();        return customer;      }catch (RuntimeException e) {        if (tx != null) {          tx.rollback();        }        throw e;      } finally {        session.close();      }    }     public void saveCustomerAndOrder(){      Session session = sessionFactory.openSession();      Transaction tx = null;      try {        tx = session.beginTransaction();         Customer customer=new Customer("Tom");//创建一个Customer持久化对象        session.save(customer);         Order order1=new Order("Tom_Order001",customer);        Order order2=new Order("Tom_Order002",customer);//创建两个Order对象        session.save(order1);        session.save(order2);       // 对同一个customerHibernate执行两次插入ORDERS表        tx.commit();       }catch (RuntimeException e) {        if (tx != null) {          tx.rollback();        }        throw e;      } finally {        session.close();      }    }        public void printOrders(List orders){        for (Iterator it = orders.iterator(); it.hasNext();) {           Order order=(Order)it.next();           System.out.println("OrderNumber of "+order.getCustomer().getName()+ " :"+order.getOrderNumber());        }    }      public void test(){        saveCustomerAndOrder();      //  saveCustomerAndOrderWithCascade();        Customer customer=findCustomer(1);        List orders=findOrdersByCustomer(customer);        printOrders(orders);    }     public static void main(String args[]){      new BusinessService().test();      sessionFactory.close();    }  }  <span style="font-size:16px;color:#cc33cc;"><strong>  </strong></span>

上述代码中方法 saveCustomerAndOrderWithCascade()如果没有session.save(customer)这一句,

执行时会抛出PropertyValueException异常,主要原因是:

在调用session.save(order1)方法之前,order1和customer对象都是临时的,临时对象是由new创建的,都是没有持久化的对象。假设 session.save(order1)被成功执行,order1会被成功持久化,变成持久化对象,但是Hibernate不会自动持久化order1所关联的customer对象。

在执行session.save(order1)时,插入ORDERS表记录的CUSTOMER_ID字段为null,这违反了数据库完整性约束,即ORDERS表中不允许CUSTOMER_ID为null。

疑问假设ORDERS表中CUSTOMER_ID字段允许为null:

<many-to-one          name="customer"         column="CUSTOMER_ID"         class="mypack.Customer"         not-null="false"           lazy="false"      />

这样执行的话,能够成功的向ORDERS表中插入两条数据;但是当Hibernate自动清理(flush)缓存中所有持久化对象时,又会抛出新的异常

org.hibernate.TransientObjectException:object references an unsaved transient instance -save the transient instance before flushing :mypack.Customer

所谓清理是指Hibernate按照持久化对象的属性变化来同步更新数据库。在清理的时候Hibernate会发现order1和order2都引用临时对象customer,而在ORDERS表中CUSTOMER_ID字段为null,这就意味着内存中持久化对象的属性和数据库中记录不一致。之所以会报错是因为order1中customer属性引用了一个临时对象Customer。

由此可见,Hibernate持久化一个对象时,默认情况下不会自动持久化所关联的其他对象。但是,我们我们希望当Hibernate持久化Order对象时自动持久化所关联的Customer对象,我们可以修改映射文件如下:

<many-to-one          name="customer"         column="CUSTOMER_ID"         class="mypack.Customer"         cascade="save-update"         not-null="false"           lazy="false"      />

当cascade属性为“save-update”,表明保存或更新对象时,会级联保存或更新与它所关联的对象。如上例中,执行saveCustomerAndOrderWithCascade()时,Hibernate会把order1与customer对象一起持久化,此时Hibernate会执行

insert into CUSTOMERS(ID,NAME) values(2,"Jack");  insert into ORDERS(ID,ORDER_NUMBER,CUSTOMER_ID) value (3,"Jack_Order001",2);

二、映射一对多双向关联关系

类类之间建立了联系,就可以很方便地从一个对象导航到另一个或者另一组与它相关联的对象。正如上例中,对于给定的Order对象,如果想获得与之关联的Customer对象,可以直接如下调用:

Customer customer=order.getCustomer();

那么对于给定的Customer对象,如何一次获得所有与之关联的Order对象呢?由于上例中Customer对象没有和Order对象关联,我们也可以通过Hibernate api去查询数据库:

List orders=session.createQuery("from Order as o where o.customer.id="+customer.getId()).list();

显然这样做的效率会很低,而且复杂的关联关系也会给编程带来影响。我们可以为Customer类和Order类简历一对多的双向关联。

第一部分我们已经建立了Order类和Customer类的多对一关联,现在我们再增加Customer到Order类的一对多关联。

Customer.java文件:

package mypack;  import java.util.HashSet;   import java.util.Set;  //Hibernate要求在持久化类中定义集合类属性时,必须要把属性声明为接口类型。   public class Customer  implements java.io.Serializable {       private long id;       private String name;       private Set orders = new HashSet();//初始化为集合实现类,这样做可以提高程序的健壮性,同时避免了应用程序访问取词为null的orders集合的方法而抛出NullPointerException。      public Customer() {      }       public Customer(String name, Set orders) {         this.name = name;         this.orders = orders;      }     //省略了id,name的get和set访问方法      public Set getOrders() {          return this.orders;      }            public void setOrders(Set orders) {          this.orders = orders;      }  }

接下来就是映射文件的配置Customer.hbm.xml:

<class name="mypack.Customer" table="CUSTOMERS" >    <id name="id" type="long" column="ID">      <generator class="increment"/>    </id>     <property name="name" type="string" >        <column name="NAME" length="15" />    </property>    <set         name="orders"       cascade="save-update"                         <key column="CUSTOMER_ID" />//表示ORDERS表通过外键CUSTOMER_ID参照CUSTOMERS表        <one-to-many class="mypack.Order" />     </set>      </class>

使用方法のBussiness.java演示分函数介绍:

(1)saveCustomerAndOrderWithCascade()方法:当映射文件中<set>的属性为“save-update”时,Hibernate在持久化Customer对象时也会自动持久化其所关联的Order对象

  public void saveCustomerAndOrderWithCascade(){      Session session = sessionFactory.openSession();      Transaction tx = null;      try {        tx = session.beginTransaction();         Customer customer=new Customer("Tom",new HashSet());        Order order=new Order();        order.setOrderNumber("Tom_Order001");         order.setCustomer(customer);        customer.getOrders().add(order);         session.save(customer);         tx.commit();        idOfTom=customer.getId();        idOfTomOrder=order.getId();                            }catch (RuntimeException e) {        if (tx != null) {          tx.rollback();        }        e.printStackTrace();      } finally {        session.close();      }    }

当映射文件中<set>的属性为“save-update”时,Hibernate在持久化Customer对象时也会自动持久化其所关联的Order对象

insert into CUSTOMERS(ID,NAME) values(1,"Tom");  insert into ORDERS(ID,ORDER_NUMBER,CUSTOMER_ID) values(1,"Tom_Order001",1)

(2)printOrdersOfCustomer(Long customerId)方法:打印与指定customerId关联的所有Order对象

public void printOrdersOfCustomer(Long customerId){    Session session = sessionFactory.openSession();    Transaction tx = null;    try {      tx = session.beginTransaction();      Customer customer=(Customer)session.get(Customer.class,customerId);      printOrders(customer.getOrders());//使用getOrders获取一个order对象set      tx.commit();    }catch (RuntimeException e) {      if (tx != null) {         tx.rollback();      }      throw e;    } finally {       session.close();    }  }

其调用的函数printOrders(Set orders)

public void printOrders(Set orders){       for (Iterator it = orders.iterator(); it.hasNext();) {          Order order=(Order)it.next();          System.out.println("OrderNumber of "+order.getCustomer().getName()+ " :"+order.getOrderNumber());       }   }

(3)saveCustomerAndOrderWithInverse()方法:演示映射文件<set>属性为inverse

public void saveCustomerAndOrderWithInverse(){        saveCustomerAndOrderSeparately();        associateCustomerAndOrder();     }

调用的函数saveCustomerAndOrderSeparately():即是分别存储,与saveCustomerAndOrderWithCascade()方法恰好相反。

Customer customer=new Customer();  customer.setName("Jack");  Order order=new Order();  order.setOrderNumber("Jack_Order001");  session.save(customer);  session.save(order);&nbsp;  tx.commit();  idOfJack=customer.getId();  idOfJackOrder=order.getId();

为了使上述代码正常执行,需要确保Order.hbm.xml文件的<many-to-one>元素的not null取默认值false,否则会出现异常;Hibernate会执行如下

insert into CUSTOMERS(ID,NAME) values(2,"Jack");  insert into ORDERS(ID,ORDER_NUMBER,CUSTOMER_ID) values(2,"Jack_Order001",null);

调用的函数associateCustomerAndOrder():该方法加载由saveCustomerAndOrderSeparately()方法持久化Customer和Order对象,然后建立两者之间的一对多的关系

public void associateCustomerAndOrder(){     Session session = sessionFactory.openSession();     Transaction tx = null;     try {       tx = session.beginTransaction();             Customer customer=(Customer)session.load(Customer.class,idOfJack);       Order order=(Order)session.load(Order.class,idOfJackOrder);             order.setCustomer(customer);       customer.getOrders().add(order);       tx.commit();     }catch (RuntimeException e) {       if (tx != null) {         tx.rollback();       }        e.printStackTrace();     } finally {       session.close();     }   }

Hibernate映射一对多关联关系是什么

这样重复执行多余的sql语句会影响java应用的性能,解决的方法是将<set>的inverse属性设为true。因此修改Customer.hbm.xml文件:

<set           name="orders"         inverse="true"         cascade="save-update"           >                    <key column="CUSTOMER_ID" />//表示ORDERS表通过外键CUSTOMER_ID参照CUSTOMERS表          <one-to-many class="mypack.Order" />  </set>

(4)级联删除:

tx = session.beginTransaction();        Customer customer=(Customer)session.load(Customer.class,customerId);        session.delete(customer);        tx.commit();

如果要删除Customer所关联的Order对象的话,需要将cascade属性设置为delete,如下:

<set          name="orders"        inverse="true"        cascade="delete"          >  <key column="CUSTOMER_ID" />         <one-to-many class="mypack.Order" />      </set>

执行后,Hibernate会做以下动作:

delete from ORDERS where CUSTOMER_ID=2;  delete from CUSTOMERS where ID=2;

如果关联双方是父子关系,就可以把复方的cascade设置为all-delete-orphan;这样删除父方对象时就会级联删除所有关联的子方对象。

三、映射一对多双向自身关联关Hibernate映射一对多关联关系是什么

Hibernate映射一对多关联关系是什么

Hibernate映射一对多关联关系是什么

CateGory.java:

package mypack;  import java.util.HashSet;  import java.util.Set;  public class Category  implements java.io.Serializable {       private long id;       private String name;       private Set childCategories = new HashSet(0);       private Category parentCategory;       public Category() {      }       public Category(String name, Set childCategories, Category parentCategory) {         this.name = name;         this.childCategories = childCategories;         this.parentCategory = parentCategory;      }           public long getId() {          return this.id;      }            public void setId(long id) {          this.id = id;      }      public String getName() {          return this.name;      }            public void setName(String name) {          this.name = name;      }      public Set getChildCategories() {          return this.childCategories;      }            public void setChildCategories(Set childCategories) {          this.childCategories = childCategories;      }      public Category getParentCategory() {          return this.parentCategory;      }            public void setParentCategory(Category parentCategory) {          this.parentCategory = parentCategory;      }  }

配置文件Category.hbm.xml:

<?xml version="1.0"?>  <!DOCTYPE hibernate-mapping  PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "Http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  <hibernate-mapping >     <class name="mypack.Category" table="CATEGORIES" >      <id name="id" type="long" column="ID">        <generator class="increment"/>      </id>       <property name="name" type="string" >          <column name="NAME" length="15" />      </property>       <set           name="childCategories"         cascade="save-update"         inverse="true"         >          <key column="CATEGORY_ID" />          <one-to-many class="mypack.Category" />       </set>         <many-to-one          name="parentCategory"         column="CATEGORY_ID"         class="mypack.Category"        />     </class>   </hibernate-mapping>

感谢各位的阅读,以上就是“Hibernate映射一对多关联关系是什么”的内容了,经过本文的学习后,相信大家对Hibernate映射一对多关联关系是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: Hibernate映射一对多关联关系是什么

本文链接: https://www.lsjlt.com/news/288590.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Hibernate映射一对多关联关系是什么
    这篇文章主要讲解了“Hibernate映射一对多关联关系是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Hibernate映射一对多关联关系是什么”吧!在域模型中,类和类之间最普通的关系...
    99+
    2023-06-17
  • hibernate 一对多 关系映射
    在关系中,或多或少的表之间有复杂的关联关系这里测试 一对多 关联关系的配置开发步骤就不多说了。直接看一个示例。users 用户 和  shop商品订单表分析:一个用户可以有多个商品订单,一个订单只...
    99+
    2022-10-18
  • Hibernate映射关联是什么
    这篇文章主要讲解了“Hibernate映射关联是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Hibernate映射关联是什么”吧!Hibernate映射关联关系和我们现实世界里事物的关...
    99+
    2023-06-17
  • hibernate 多对多关系映射
    学生 和 课程就是一种多对多的关系映射,那么再hibernate中,对于多对多关系在怎么配置?和一些注意的事项?简单测试下。建表实体配置文件和映射测试1。使用oracle ,建表sqlcreate ...
    99+
    2022-10-18
  • Java Hibernate中一对多和多对多关系的映射方式
    目录Hibernate的一对多和多对多Hibernate的一对多Hibernate的一对多配置Hibernate的一对多操作Hibernate的多对多Hibernate的多对多配置H...
    99+
    2023-05-18
    Java Hibernate一对多 Java Hibernate多对多
  • Hibernate一对多数据关联是什么
    本篇内容主要讲解“Hibernate一对多数据关联是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Hibernate一对多数据关联是什么”吧!Hibernate一对多数据关联。指的是单向一对...
    99+
    2023-06-17
  • hibernate中的对象关系映射
    Hibernate的本质就是对象关系映射(ObjectRelational Mapping),ORM实现了将对象数据保存到数据库中,以前我们对关系表进行操作,执行增删改查等任务,现在我们不再对关系表进行操作,而是直接对对象操作。hibern...
    99+
    2023-05-31
    hibernate 映射 te
  • 详解hibernate双向多对多关联映射XML与注解版
    双向多对多关联映射原理:假设,一个员工可能有多个角色,一个角色可能有多个员工,从员工或角色的角度看,这就是多对多的关系,不管从哪一个角度看,都是多对多的联系。多对多关联映射关系一般采用中间表的形式来实现,即新增一种包含关联双方主键的表。实现...
    99+
    2023-05-31
    hibernate 映射 te
  • Hibernate映射之基本类映射和对象关系映射详解
    回想一些我们在没有学习ssh的时候,我们建立数据库的表时,首先是数据库建模E-R图,然后再通过实体模型来建立关系模型,再建立相应的表。实体间存在三种关系,一对一,一对多(或者说多对一),多对多。而如今我们要根据类来映射相应的表,那只能是通过...
    99+
    2023-05-31
    hibernate 对象 映射
  • Hibernate对象关系映射举例分析
    本篇内容介绍了“Hibernate对象关系映射举例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!同样由于Hibernate官方文档的影响...
    99+
    2023-06-17
  • 浅谈hibernate中多表映射关系配置
    1.one-to-many 一对多关系的映射配置(在一的一方实体映射文件中配置)<!-- cascade属性:级联操作属性 save-update: 级联保存,保存客户时,级联保存客户关联的联系人 delete:级联...
    99+
    2023-05-31
    hibernate 多表 映射关系
  • Hibernate继承关系树的映射方式是什么
    这篇文章主要介绍“Hibernate继承关系树的映射方式是什么”,在日常操作中,相信很多人在Hibernate继承关系树的映射方式是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Hibernate继承关系...
    99+
    2023-06-17
  • MyBatis多对多关联映射创建示例
    目录示例【通过班级查询老师信息】示例 【通过班级查询老师信息】 创建t_classes 创建t_classessTeacher 创建t_teacher 创建Classes pa...
    99+
    2022-11-13
  • mybatis如何实现一对一关联映射
    小编给大家分享一下mybatis如何实现一对一关联映射,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!前言在客观世界中,对象很少是孤独存在的,如班级与学生之间的关系...
    99+
    2023-05-30
    mybatis
  • Hibernate一对多数据关联怎么实现
    本篇内容主要讲解“Hibernate一对多数据关联怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Hibernate一对多数据关联怎么实现”吧!数据模型表定义sqluse sam...
    99+
    2023-06-17
  • SpringDataJpa的使用之一对一、一对多、多对多 关系映射问题
    目录SpringDataJpa的使用 -- 一对一、一对多、多对多 关系映射项目依赖项目配置sql文件(MySQL版)级联关系简述@OneToOne 一对一 关系映射1.无中间表,维...
    99+
    2022-11-13
  • Hibernate的一对一,一对多/多对一关联保存的实现
    目录一对一关联保存:留言表实体类配置:(主表)留言内容表配置:(从表)留言表hbm.xml配置:(主表)留言内容表hbm.xml配置:(从表)一对多/多对一保存活动表实体类配置:(主...
    99+
    2022-11-12
  • 对象关系映射ORM的缺点是什么
    对象关系映射ORM的缺点是什么?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。对象关系映射(ORM)提供了概念性的、易于理解的模...
    99+
    2022-10-18
  • 利用Hibernate怎么实现一个多对一单项关联
    这期内容当中小编将会给大家带来有关利用Hibernate怎么实现一个多对一单项关联,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。概念      ...
    99+
    2023-05-31
    hibernate te
  • 对象关系映射ORM有什么优点
    这篇文章将为大家详细讲解有关对象关系映射ORM有什么优点,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。对象关系映射(ORM)提供了概念性的、易于理解的模型化...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作