hibernate 一对一,一对多,多对多关联关系使用
2019-01-18 本文已影响46人
一名程序猿
关系型数据库
关系数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。现实世界中的各种实体以及实体之间的各种联系均用关系模型来表示。关系模型是由埃德加·科德于1970年首先提出的,并配合“科德十二定律”。现如今虽然对此模型有一些批评意见,但它还是数据存储的传统标准。标准数据查询语言SQL就是一种基于关系数据库的语言,这种语言执行对关系数据库中数据的检索和操作。 关系模型由关系数据结构、关系操作集合、关系完整性约束三部分组成。
简单说,关系型数据库是由多张能互相联接的二维行列表格组成的数据库。
一对一关系处理
one class
package com.example.demo.entity.onetoone; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToOne; import lombok.Getter; import lombok.Setter; @Entity @Getter @Setter public class One { @Id @GeneratedValue private String id; private String name; @OneToOne private Two two; }
two class
@Entity @Getter @Setter public class Two { @Id @GeneratedValue private String id; private String name; }
默认建表结构
一对一
一对一
如果我们只是单纯的在两个实体类中分别加上@OneToOne注解,会发现两张表都分别引入了对方的主键作为外键。明显的数据冗余,毕竟关系不用双方存储。
利用mappedBy属性,指明关系由哪一方维护。
一对多关系处理
创建两个实体对象,分别对应一与多的一方。
情况1-只在多的一方在@ManyToOne注解one方
package com.example.demo.entity.onetomany; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import lombok.Getter; import lombok.Setter; @Entity @Getter @Setter public class OneObject { @Id @GeneratedValue private String id; private String name; }
many方
package com.example.demo.entity.onetomany; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToOne; import lombok.Getter; import lombok.Setter; @Entity @Getter @Setter public class ManyObject { @Id @GeneratedValue private String id; private String name; @ManyToOne private OneObject object; }
此时我只在多的一方加了一个ManyToOne注解。生成表结构关系如下
只有ManyToOne一个注解
默认是在many_object里面加了一个外键列
只有ManyToOne列属性
情况2-只在one的一方加
只有一个OneToMany注解
默认情况下是生成了一张关系表。用户维护一对多关系。
关系表
至于默认的表名列名,大家可以去看生成规则。不在这篇文章研究范围。
情况3-不想生成关系表,想通过列名维护。
此时使用@JoinColumn属性。
one方@OneToMany @JoinColumn(name="obj_id") private List<ManyObject> manyObject;
many方
@ManyToOne(fetch=FetchType.EAGER,cascade=CascadeType.ALL) @JoinColumn(name="obj_id") private OneObject object;
加上@JoinColumn属性表结构
扩展
在一对多双方都设置了关联关系后,进行数据存储模拟
@Test public void contextLoads() { OneObject object = new OneObject("1"); object.setManyObject(new ArrayList<ManyObject>()); ManyObject manyObject = new ManyObject("ysh"); ManyObject manyObject2 = new ManyObject("ysh2"); object.getManyObject().add(manyObject); object.getManyObject().add(manyObject2); mp.save(manyObject); mp.save(manyObject2); op.save(object); }
控制端打印sql如下
除了三条insert数据。还有两条update语句。这个很好理解。先插入多的一方数据,然后在把one对应的一方关联加进去。
想要避免这种多余sql。有两种方式。
方法一:直接把one对应的一方赋值给多的一方。(上面是把多的一方赋值给one的一方)public void contextLoads() { OneObject object = new OneObject("1"); object.setManyObject(new ArrayList<ManyObject>()); ManyObject manyObject = new ManyObject("ysh"); ManyObject manyObject2 = new ManyObject("ysh2"); manyObject.setObject(object); manyObject2.setObject(object); // object.getManyObject().add(manyObject); // object.getManyObject().add(manyObject2); op.save(object); mp.save(manyObject); mp.save(manyObject2); }
控制台日志
可以看到update语句已经没有了。
方法二:利用OneToMany注解里面的mappedBy属性@OneToMany(mappedBy = "object") // @OneToMany // @JoinColumn(name="obj_id") private List<ManyObject> manyObject;
注意mappedBy不能与@JoinColumn注解连用
利用mappedBy属性后的输出
可以看到也实现了减少两条sql的功能。算是小功能优化。
多对多
正常建立两个多对多关系实体
1.多对多实体一package com.example.demo.entity.manytomany; import java.util.List; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToMany; import lombok.Getter; import lombok.Setter; @Getter @Setter @Entity public class Manyone { @Id @GeneratedValue private Long id; private String name; @ManyToMany private List<Manytwo> manytwos; }
多对多实体二
package com.example.demo.entity.manytomany; import java.util.List; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToMany; import lombok.Getter; import lombok.Setter; @Getter @Setter @Entity public class Manytwo { @Id @GeneratedValue private Long id; private String name; @ManyToMany private List<Manyone> manyones; }
表结构
很显然的关系表冗余。
利用@ManyToMany(mappedBy="manytwos")的mappedBy属性将关系表改为由一端维护。生成表结构如下:
表结构
cascade属性
public enum CascadeType { /** Cascade all operations */ ALL, /** Cascade persist operation */ PERSIST, /** Cascade merge operation */ MERGE, /** Cascade remove operation */ REMOVE, /** Cascade refresh operation */ REFRESH, /** * Cascade detach operation * * @since Java Persistence 2.0 * */ DETACH }
fetch属性
FetchType.LAZY:懒加载,加载一个实体时,定义懒加载的属性不会马上从数据库中加载。
FetchType.EAGER:急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。
结语
本文属于基础篇。觉得不错也可以点亮下方小星星。