hibernate 一对一,一对多,多对多关联关系使用

关系型数据库

关系数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。现实世界中的各种实体以及实体之间的各种联系均用关系模型来表示。关系模型是由埃德加·科德于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;

}

默认建表结构

hibernate 一对一,一对多,多对多关联关系使用_第1张图片
一对一

hibernate 一对一,一对多,多对多关联关系使用_第2张图片
一对一

如果我们只是单纯的在两个实体类中分别加上 @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注解。生成表结构关系如下


hibernate 一对一,一对多,多对多关联关系使用_第3张图片
只有ManyToOne一个注解

默认是在many_object里面加了一个外键列


hibernate 一对一,一对多,多对多关联关系使用_第4张图片
只有ManyToOne列属性

情况2-只在one的一方加
hibernate 一对一,一对多,多对多关联关系使用_第5张图片
只有一个OneToMany注解

默认情况下是生成了一张关系表。用户维护一对多关系。


hibernate 一对一,一对多,多对多关联关系使用_第6张图片
关系表

至于默认的表名列名,大家可以去看生成规则。不在这篇文章研究范围。
情况3-不想生成关系表,想通过列名维护。
此时使用@JoinColumn属性。
one方
  @OneToMany
  @JoinColumn(name="obj_id")
  private List manyObject;

many方

  @ManyToOne(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
  @JoinColumn(name="obj_id")
  private OneObject object;
hibernate 一对一,一对多,多对多关联关系使用_第7张图片
加上@JoinColumn属性表结构

扩展

在一对多双方都设置了关联关系后,进行数据存储模拟

  @Test
  public void contextLoads() {
      OneObject object = new OneObject("1");
      
      object.setManyObject(new ArrayList()); 
      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);                
  }

hibernate 一对一,一对多,多对多关联关系使用_第8张图片
控制端打印sql如下

除了三条insert数据。还有两条update语句。这个很好理解。先插入多的一方数据,然后在把one对应的一方关联加进去。
想要避免这种多余sql。有两种方式。
方法一:直接把one对应的一方赋值给多的一方。( 上面是把多的一方赋值给one的一方

  public void contextLoads() {
      OneObject object = new OneObject("1");
      
      object.setManyObject(new ArrayList()); 
      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);
  }

hibernate 一对一,一对多,多对多关联关系使用_第9张图片
控制台日志

可以看到update语句已经没有了。
方法二:利用OneToMany注解里面的mappedBy属性

  @OneToMany(mappedBy = "object")
  // @OneToMany
  // @JoinColumn(name="obj_id")
  private List manyObject;

注意mappedBy不能与@JoinColumn注解连用

hibernate 一对一,一对多,多对多关联关系使用_第10张图片
利用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 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 manyones;
}
hibernate 一对一,一对多,多对多关联关系使用_第11张图片
表结构

很显然的关系表冗余。
利用@ManyToMany(mappedBy="manytwos")的mappedBy属性将关系表改为由一端维护。生成表结构如下:


hibernate 一对一,一对多,多对多关联关系使用_第12张图片
表结构

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:急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。

结语

本文属于基础篇。觉得不错也可以点亮下方小星星。

你可能感兴趣的:(hibernate 一对一,一对多,多对多关联关系使用)