数据库中的表是有关系的,两个表之间可以通过外键关联。如果把表抽象为实体类,这些关系可以抽象为实体之间的一对一,一对多,多对一等关系。hibernate能处理这些复杂的关系,前提是要正确配置这些关系。

单边的一对多关系

单边的一对多关系是指一方有集合属性,包含多个多方,而多方没有一方的引用。比较典型的是用户与电子邮件。其中,用户为一方,电子邮件为多方,一个用户可以拥有多个电子邮件记录。

Person.java中有id、name、List<Email>;

Email.java中有id、email;

一个person有多个email,而email中没有person;

对应的表中

tb_person:id、name;

tb_email:id、email、person_id;

若person中有email外键,则一个person的email外键要有多个id,不现实;而email中有person外键,一个email只需要有一个person的外键即可

总结:

一个person有多个email,则person类中有多个email,而person表中没有email外键,email表中有person外键;

具体实现如下:

Person.java

package com.lmb.hibernate.bean;import java.util.ArrayList;
import java.util.List;import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;@Entity
@Table(name="tb_person")
public class Person {@Id@GeneratedValue(strategy=GenerationType.AUTO)private Integer id;private String name;//一对多配置,并配置列关系<span style="color:#ff0000;">@OneToMany(fetch=FetchType.EAGER,targetEntity=Email.class,cascade={CascadeType.PERSIST,CascadeType.REMOVE,CascadeType.MERGE,CascadeType.REFRESH})@JoinColumns(value = { @JoinColumn(name="person id",referencedColumnName="id") })//配置排序方法@OrderBy(value="email desc")
</span>   private List<Email> emails=new ArrayList<Email>();public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<Email> getEmails() {return emails;}public void setEmails(List<Email> emails) {this.emails = emails;}}

Person实体中使用@OneToMany配置一对多关系。fetch配置加载方式(延迟加载fetch=FetchType.LAZY、即时加载fetch=FetchType.EAGER);targetEntity配置集合属性中的类型,由于emails属性类型为List<Email>,用反省制定了集合内为Email对象,因此targetEntity可省略;cascade配置级联方式,本例配置为PERSIST、REMOVE、MERGE、REFRESH,表示在保存、删除、修改、刷新Person类时会自动在数据库中保存、删除、修改、刷新属于它的Email对象。配置级联关系后,可以通过操作Person类来操作Email类。该配置也等同于CascadeType.ALL。@OrderBy配置排序方式,本例将Email按照email列降序排列。

Email实体类比较简单,由于是单边关系映射,Email中没有用户实体的引用,只是一个简单的POJO。

Email.java

package com.lmb.hibernate.bean;import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;@Entity
@Table(name="tb_email")
public class Email {@Id@GeneratedValue(strategy=GenerationType.AUTO)private Integer id;private String name;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}}

配置完毕后要将Person类和Email类在hibernate配置文件中声明为实体类。实体类要配置在<session-factory  />中。

hibernate.cfg.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration><session-factory><property name="dialect">org.hibernate.dialect.MySQLDialect</property><property name="connection.url">jdbc:mysql://localhost:3306/hibernate?characterEncoding=UTF-8</property><property name="connection.username">lmb</property><property name="connection.password">lmb</property><property name="connection.driver_class">com.mysql.jdbc.Driver</property><span style="color:#ff0000;"><mapping class="com.lmb.hibernate.bean.Person" /><mapping class="com.lmb.hibernate.bean.Email" />
</span>    </session-factory></hibernate-configuration>

以上使用@注解实现的,当然我们还可以使用XML配置的方式实现,这了我就不在列出。

延迟加载与即时加载

即时加载(Eagar Fetching),查询Person的时候自动加载相关的Email

延迟加载(Lazy Fetching),只有在需要的时候才查询Email(默认)

延迟加载异常

一般来说,延时加载比即时加载节省资源。但是如果处理不当,延迟加载容易抛出延时加载异常(LazyInitializationException)。这是因为延迟加载时,只有第一次调用person.getEmail()才会加载emails数据,如果这时候数据库连接已经关闭了,就会因为无法加载数据而抛出异常。

解决办法:(两种)

1、在session关闭前调用一次上面的方法(person.getEmail()),强迫hibernate加载Email数据;session关闭后JDBC连接就关闭了,无法再从数据库读取任何数据了。

2、延迟session的范围,使session关闭前完成所有的业务逻辑。

【Hibernate】Hibernate实体映射——单边的一对多关系相关推荐

  1. 【Hibernate】Hibernate实体关系映射——单边的多对一关系

    单边的多对一关系 单边的多对一关系与单边的一对多关系刚好相反,多方有一方的引用,一方没有多方的引用,但是他们的数据表间的关系是一样的.例如:论文与论文类别: 具体实现如下: Type实体类的java注 ...

  2. 【Hibernate】hibernate实体关系映射——单边的多对多关系

    //刘梦冰发表于2015-6-19 单边的多对多关系 多对一.一对多的关系只需要两个表即可,使用子表的外键与主表的主键连接就能存储主从关系.而对多对多的关系至少需要三个表,其中两个表保存两个实体类,另 ...

  3. 【HibernateHibernate实体关系映射——双边的多对一、一对多关系

    双边的多对一.一对多关系 双边关系是最常见的配置.在多方有一方的引用,一方也有多方的引用.双边关系能够很方便的查询数据.下面以一个班级与学生的双边关系来深入学习. 班级(clazz类)与学生(stud ...

  4. jpa 实体映射视图_JPA教程:映射实体–第1部分

    jpa 实体映射视图 在本文中,我将讨论JPA中的实体映射过程. 至于我的示例,我将使用与 我以前的一篇文章中使用的模式相同的模式 . 在前两篇文章中,我解释了如何在Java SE环境中设置JPA. ...

  5. 【Hibernate】Hibernate实体关系映射——单边的一对一关系

    //刘梦冰发表于2015-6-19 一对对一关系的情况要多一些,不仅在POJO层体现为一对一的,还要保证数据库中的关系是一对一的,不允许出现一个表的两行记录共用另一个表中同一行记录的情况.这可以通过设 ...

  6. hibernate的映射之二(一对多双向关联)

    hibernate的一对多双关联 一对多关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是一指向多 hihernate一对多关联映射(双向Dept<----->Emp) 一对多双 ...

  7. Hibernate的关联映射--一对多、

    这是我 1 单向一对多: 实体类:(课程类)Grade与(学生类)Student的一对多关系 学生类: public class Student implements java.io.Serializ ...

  8. 角色和权限Hibernate实体映射配置

    角色实体 package cn.itcast.oa.domain;import java.util.HashSet; import java.util.Set;/*** 岗位* * @author t ...

  9. hibernate中一对多关系的映射

    昨天初次接触hibernate,仅仅弄懂了一对一关系的映射.今天学习了一天又有了新的收获,弄懂了一对多之间关系的映射. 一.一对多的关系映射 建立一对多关系关系的表的原则是将一的一方的主键加入到多的一 ...

最新文章

  1. PPIO 商业化架构解析
  2. erlang精要(14)-列表(1)
  3. windows键盘在mac上怎么识别_Mac电脑怎么使用pc键盘?
  4. excelexportentity中设置null不显示的方法_学习笔记-Java中的$符
  5. 我爬了价值1800亿的商品信息
  6. linux机器光口和电口的区别,易天光通信SFP电口模块和10G SFP+电口模块介绍
  7. 查找算法之三 插值查找(C++版本)
  8. python中33个保留字的含义_Python的保留字。这是什么意思?
  9. KVM-QEMU的vCPU调度算法与Xen Credit算法对比分析
  10. bandzip、winzip与7-zip
  11. 后台网站二级页面制作步骤
  12. 基于Pytorch构建一个可训练的BNN
  13. 赛季更新服务器维修,12月30日第一赛季结束 夺神之权服务器停机维护公告
  14. ECMALL买家取消退款
  15. 啊,这该死的天气和路况,让我特靠谱爱车失灵了《打工人的那些事》
  16. Python中flask_sqlalchemy的使用
  17. C语言实现流媒体广播项目
  18. 用mplab x ipe进行联机以及脱机的烧写
  19. k8s+Jenkins+GitLab-自动化部署tomcat项目
  20. Linux Shell find命令只输出文件名字,不携带路径

热门文章

  1. [转] Apache日志分析常用Shell命令
  2. error2---BeginPath和EndPath之间的TextOut无法显示
  3. Boke宝贝 - 免费提供图片存储空间、计数器、留言板
  4. Android Activity为什么要细化出onCreate、onStart、onResume、onPause、onStop、onDesdroy这么多方法让应用去重载?
  5. BitNami Redmine Stack
  6. Android 入职感想
  7. Android窗口View层次
  8. 【Redis】18.缓存预热、缓存雪崩、缓存击穿、缓存穿透、性能指标监控等企业级解决方案
  9. IO多路复用 select、poll、epoll
  10. Spring框架—SpringBean配置