专栏首页帅哥哥写代码hibernate 一对一,一对多,多对多关联关系使用

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;

}

默认建表结构

一对一

一对一 如果我们只是单纯的在两个实体类中分别加上@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 lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
public class OneObject {

  @Id
  @GeneratedValue
  private String id;
  private String name;
  
}

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

结语

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JPA关联关系表中加其他字段

    JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体[对...

    用户5166330
  • 自定义工作流设计

    工作偶尔会遇到需要审批相关的系统,对于流程步骤相对固定的,一般会采取某些第三方的工作流来做对应的系统。目前唯一用过的就是activiti工作流。对它进行了简单的...

    用户5166330
  • sql功底展示

    用户5166330
  • Spring Boot 整合Mybatis

    可以直接在Springboot的主入口处添加 @MapperScan 扫描指定路径的mapper,就不用在每个dao上都加一个@mapper 注解了。

    LCyee
  • Java 单例模式 五种常见的写法

    大数据工程师-公子
  • JPA关联关系表中加其他字段

    JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体[对...

    用户5166330
  • 浅淡Java设计模式之单例模式

    什么是单例模式? 保证一个类仅有一个实例,并提供一个访问它的全局访问点. java中的单例:一个类有且仅有一个实例,并且自行实例化向整个系统提供。

    聚沙成塔
  • 隐私硬币概述

    隐私硬币是像比特币这样的加密货币的演变。比特币交易是匿名的,因为每个钱包的所有者都是未知的,但每笔交易都是在公共账本上公开广播和可见的。这意味着指定钱包的所有交...

    DEXIN
  • 基于TrueLicense实现产品License验证功能

    2、  授权者保留私钥,使用私钥对包含授权信息(如截止日期,MAC地址等)的license进行数字签名。

    朝雨忆轻尘
  • 谁说程序员不能潮?高颜值红包开启你的RICH年

    点击底部“阅读原文”,在指定微博留言“你最有福气的经历”并关注@腾讯WeTest,我们将随机选出3位幸运儿送出新春行运红包哦!

    WeTest质量开放平台团队

扫码关注云+社区

领取腾讯云代金券