Hibernate实体关系映射
来源:互联网 发布:centos的vmdk文件下载 编辑:程序博客网 时间:2024/05/01 03:47
概要
数据库中的表是有关系的,两个表之间可以通过外键关联。
关系有:一对一、一对多、多对一、多对多等。
要使Hibernate正确处理这些关系,需要正确的配置。
常用注解
@OneToMany
@OneToOne
@ManyToOne
@ManyToMany
名词解释
- 什么是单边?双边?
单边指一边有另一边对象引用,一边没有。
双边指双边都有对方对象的引用。
单边OneToMany例子
以“用户”和“Email”为例,一个用户可以拥有多个电子邮箱
tb_person(用户表):id、name
tb_email(Email表):id、email、person_id(外键,参考用户表的id)
@OneToMany(fetch=FetchType.EAGER,targetEntity=Email.class,cascade={CascadeType.PERSIST,Cascade.REMOVE,Cascade.MERGE,Cascade.REFRESH})//相当于Cascade.ALL设置级联关系,上面分别表示:保存、删除、修改、刷新时@JoinColumns(Value={@JoinColumn(name="person_id",referencedColumnName="id")})@OrderBy(value="email desc")private List<Email> emails=new ArrayList<Email>();//外键
延迟加载和即时加载
fetch=FetchType.LAZY / FetchType.EAGER
例如上面的“人”这个实体,设置对Email是即时加载的话,在加载Person的时候就会加载Email,而使用延迟加载在调用Email的get方法时才会去加载
一般来说延迟加载比即时加载节省资源,尤其是关联的表数量较多的时候,但是使用延迟加载,假如在调用email的get方法之前已经关闭了session,会导致加载email异常。
单边ManyToOne例子
以“博文”和“类型”为例
tb_blog(博文表):id、content(longtext类型)、type_id(外键,参考类型表的id)
tb_type(类型表):id、name(unique)
@ManyToOne(cascade={CascadeType.PERSIST},fetch=FetchType.EAGER)@JoinColumn(name="type_id")Private Type type;
双边的OneToMany和ManyToOne例子
以“班级”和“学生”为例
tb_class(班级表):id、name、
tb_student(学生):id、name、sex、class_id(外键)
在双边关系中,控制权一般交给多方,因此下面使用反向配置。假如像之前的单边一对多关系配置,则控制权在一方
Clazz.java实体的配置
@OneToMany(mappedBy="clazz")//反向配置,告诉Hibernate,配置信息在Student类的clazz属性找private List<Student> students=new ArrayList<Student>();
Student.java实体配置
@ManyToOne(fetch=FetchType.EAGER,cascade={Cascade.PERSIST})@JoinColumn(name="class_id")private Clazz clazz;
单边ManyToMany例子
多对多关系至少需要三张表,两个表用来保存实体类,另一张表保存两个实体的关系
这里以“博文”和“标签”为例
tb_blog(博文表):id、name、content
tb_tag(标签表):id、name
tb_blog_tag(关系表):b_id、t_id
Blog.java配置
@ManyToMany(fetch=FetchType.EAGER,cascade={CASCADE.PERSIST})@JoinTable( name="tb_blog_tag", joinColumns=@JoinColumn(name="b_id",referenceColumnName="id"), inversJoinColumns=@JoinColumn("t_id",referenceColumnName="id"))private Set<Tag> tags=new HashSet<Tag>();
使JoinTable来指定中间表
joinColumns指定该表(例子中为blog表)与中间表的关系
inverJoinColumns指定另一张表(例子中为tag表)与中间表的关系
双边ManyToMany例子
在上面单边ManyToMany例子基础上,对Tag实体增加ManyToMany配置
Tag.java
@ManyToMany(mappedBy="tags") //反向配置private Set<Blog> blogs=new Set<Blog>();
单边OneToOne例子
以”飞机”和”机务人员”为例
一个机长只对应一辆飞机
tb_plane(飞机表):id、name、captain_id
tb_crew(机务人员表):id、name、plane_id
Plane.java
@OneToOne(cascade={CascadeType.PERSIST,CascadeType.REFRESH})@JoinColumn(name="captain_id",unique=true)private Crew captain;@OneToMany(mappedBy="plane",cascade=CascadeType.PERSIST)private Set<Crew> crews=new HashSet<Crew>();
Crew.java
@ManyToOne(cascade=CascadeType.PERSIST)@JoinColumn(name="plane_id")private Plane plane;
双边OneToOne例子
在上面单边OneToOne的基础上,修改Sailor.java
增加
@OneToOne(mappedBy="captain")private Ship captainedShip;
主键相同的OneToOne例子
以“客户”和“客户唯一地址”为例
客户和地址使用相同的主键
tb_customer(客户表):id、name
tb_address(地址表):id、address
Customer.java
@Id@GeneratedValue(stratety=GenerationType.AUTO)private Integer id;//...@OneToOne@PrimaryKeyJoinColumnprivate Address address;
Address.java
@Idprivate Integer id;//不能使用自增长Id@OneToOne@PrimaryKeyJoinColumnprivate Customer customer;
要注意的一些点
- 使用XML配置文件来配置实体间的关系功能要多得多
- XML可以使用String等基本类型来作为实体,而注解方式,实体必须为一个POJO。
- 一对多关系中,常常将主动权给多方,一方常常使用反向配置
- referencedColumnName默认是表的主键,如果为主键可省去
- 在List<>,Set<>等泛型中指定了类名,可以在关系注解中省略targetEntity属性
- Hibernate实体关系映射
- Hibernate实体关系映射
- hibernate实体关系映射
- hibernate实体关系映射
- Hibernate实体关系映射
- hibernate 实体关系映射笔记
- Hibernate之实体关系映射
- Hibernate之实体关系映射
- Hibernate 实体关联关系映射
- Hibernate实体关系映射技巧
- Hibernate 实体关联关系映射----总结
- Hibernate 实体关联关系映射----总结
- Hibernate 实体关联关系映射----总结
- Hibernate 映射实体关联关系(一)
- Hibernate 映射实体关联关系(二)
- Hibernate 实体关联关系映射----总结
- Hibernate 实体关联关系映射----总结
- Hibernate 实体关联关系映射----总结
- JSON Views 高级用法
- MAC通用终端(terminal)光标的移动
- Java经典设计模式(2):七大结构型模式(附实例和详解)
- fatal error C1083: 无法打开预编译头文件 正确解法
- Android ListView默认选中某一项
- Hibernate实体关系映射
- javascript基础一 (DOM基础一)
- 【BZOJ4198】[Noi2015]荷马史诗【k叉Huffman树】【贪心】
- 安装JDK
- 可重入函数/不可重入函数
- 【QT】:QT中的信号和槽
- IIS发布时的注意事项
- python 数据结构
- angular学习(一)—— 概览