spring jpa ManyToMany原理及用法详解

1.java和jpa 中所有的关系都是单向的。这个关系数据库不同,关系数据库,通过外键定义并查询,使得反向查询总是存在的。

2.JPA还定义了一个OneToMany关系,它与ManyToMany关系类似,但反向关系(如果已定义)是ManyToOne关系。

OneToMany与JPA中ManyToMany关系的主要区别在于,ManyToMany总是使用中间关系连接表来存储关系,

OneToMany可以使用连接表或者目标对象的表引用中的外键源对象表的主键。

@OneToMany(cascade = CascadeType.ALL)
  @JoinColumn(name = "OPR_WARE_SYSCONFIG_ID",foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
  private List<WarehouseVO> warehouse;

wareHouseVO的表通过外键字段关联,而定义了OneToMany的属性的VO则不需要添加表字段。

ManyToOne:

@ManyToOne
  @JoinColumn(name = "OPR_WAREHOUSE_ENV_ID")
  private EnvironmentVO env ;

总结,作为many的一方需要有外键关联One的一方。

@ManyToMany 注解

manyToMany需要和@JoinTable表结合使用,ManyToMany总是使用中间关系连接表来存储关系。如果两个Vo都定义了ManyToMany的话,因为单向关系,会生成有2个中间表。所以需要改造成双向关系,使其只存在一个中间表。

例子:

a:一方不需要mappedBy属性,一方需要。

@ManyToMany
  @JoinTable(name = "AUTO_SYSTEM", joinColumns = { @JoinColumn(name = "OPR_AUTO_ID") }, inverseJoinColumns = {
      @JoinColumn(name = "OPR_SYSTEM_ID") }, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT), inverseForeignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
  private List<SystemVO> systems;
@ManyToMany(mappedBy = "students")
private List<Service> services;

b:

@Entity
public class Student {
  @Id
  private String id;
  @ManyToMany
  @JoinTable
  private List<Teacher> teachers;
}

@Entity
public class Teacher {
  @Id
  private String id;
  @ManyToMany
  @JoinTable
  private List<Student> students;
}

@ManyToMany即表示了老师和学生的多对多关系。@ManyToMany注解可以用在字段或方法上

但是这样会有两个表出现,TEACHER_STUDENTS表和STUDENT_TEACHERS。

原因是这里的多对多关系正是维基百科提到的单向原则。老师和学生虽然分别定义了自己的多对多关系,但这个关系都是单向的,要使关系成为双向。

mappedBy 属性

mappedBy是OneToOne、OneToMany和ManyToMany这三种关联关系的属性。

用来标注拥有这种关系的字段。 除非关系是单向的,否则是必需的。

什么叫拥有关联关系呢,假设是双向一对一的话,那么拥有关系的这一方有建立、解除和更新与另一方关系的能力。而另一方没有,只能被动管理。

由于JoinTable和JoinColumn一般定义在拥有关系的这一端,而mappedBy一定是定义在关系的被拥有方(the owned side),也就是跟定义JoinTable

和JoinColumn互斥的一方,它的值指向拥有方中关于被拥有方的字段,可能是一个对象(OneToMany),也可能是一个对象集合(ManyToMany)。

@Entity
public class Student {
  @Id
  private String id;
  @ManyToMany(mappedBy = "students")
  private List<Teacher> teachers;
}

@Entity
public class Teacher {
  @Id
  private String id;
  @ManyToMany
  @JoinTable(“student”)
  private List<Student> students;
}

这时中间表只有一张TEACHER_STUDENTS,关联关系也变成了我们想要的双向关系。

Cascade 级联关系

实际业务中,我们通常会遇到以下情况:

1.用户和用户的收货地址是一对多关系,当用户被删除时,这个用户的所有收货地址也应该一并删除。

2.订单和订单中的商品也是一对多关系,但订单被删除时,订单所关联的商品肯定不能被删除。

此时只要配置正确的级联关系,就能达到想要的效果。

级联关系类型:

  • CascadeType.REFRESH:级联刷新,当多个用户同时作操作一个实体,为了用户取到的数据是实时的,在用实体中的数据之前就可以调用一下refresh()方法
  • CascadeType.REMOVE:级联删除,当调用remove()方法删除Order实体时会先级联删除OrderItem的相关数据
  • CascadeType.MERGE:级联更新,当调用了Merge()方法,如果Order中的数据改变了会相应的更新OrderItem中的数据
  • CascadeType.ALL:包含以上所有级联属性
  • CascadeType.PERSIST:级联保存,当调用了Persist() 方法,会级联保存相应的数据

需要注意的是,CascadeType.ALL要谨慎使用,为了达到数据同步,很多人喜欢用CascadeType.ALL来实现。但上面订单和商品的例子就不适用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 使用SpringBoot-JPA进行自定义保存及批量保存功能

    说明 SpringBoot版本:2.1.4.RELEASE java版本:1.8 文中所说JPA皆指spring-boot-starter-data-jpa 使用JPA保存一个Student对象 在JPA中保存一个对象,仅需要该对象,一个仓储即可. StudentDO实体类: @Getter @Setter @Entity @Table(name = "t_student") public class StudentDO { @Id @GeneratedValue(strategy =

  • spring+Jpa多数据源配置的方法示例

    今天临下班时遇到了一个需求,我的管理平台需要从不同的数据库中获取数据信息,这就需要进行Spring的多数据源配置,对于这种配置,第一次永远都是痛苦的,不过经历了这次的折磨,今后肯定会对这种配置印象深刻.我们这里简单回顾一下流程. 我们配置了两个数据库,一个是公司的数据库,另一个是我本地的一个数据库.首先是application.yml的配置(其中对于公司的数据库我们采取了假的地址,而本机的数据库是真是存在对应的表和库的) 数据库信息: 数据表信息: 1.application.yml datas

  • 详解SpringBoot实现JPA的save方法不更新null属性

    序言:直接调用原生Save方法会导致null属性覆盖到数据库,使用起来十分不方便.本文提供便捷方法解决此问题. 核心思路 如果现在保存某User对象,首先根据主键查询这个User的最新对象,然后将此User对象的非空属性覆盖到最新对象. 核心代码 直接修改通用JpaRepository的实现类,然后在启动类标记此实现类即可. 一.通用CRUD实现类 public class SimpleJpaRepositoryImpl<T, ID> extends SimpleJpaRepository&l

  • SpringBoot集成Spring Data JPA及读写分离

    相关代码: github OSCchina JPA是什么 JPA(Java Persistence API)是Sun官方提出的Java持久化规范,它为Java开发人员提供了一种对象/关联映射工具 来管理Java应用中的关系数据.它包括以下几方面的内容: 1.ORM映射 支持xml和注解方式建立实体与表之间的映射. 2.Java持久化API 定义了一些常用的CRUD接口,我们只需直接调用,而不需要考虑底层JDBC和SQL的细节. 3.JPQL查询语言 这是持久化操作中很重要的一个方面,通过面向对象

  • Spring Data Jpa 自动生成表结构的方法示例

    想在部署的时候随应用的启动而初始化数据脚本,这不就是Spring Data Jpa中的自动生成表结构,听起来特别简单,不就是配置Hibernate的ddl-auto嘛,有什么好说的,是个人都知道.当初我也是这样认为,实际操作了一把,虽然表是创建成功了,但是字段注释,字符集以及数据库引擎都不对,没想到在这些细节上翻车了. 毕竟开翻的车还要自己扶起来,于是在这记录一下. 注:本文中使用的Spring Data Jpa版本为2.1.4.RELEASE 以MySQL为例,我这边举个例子: import

  • Spring Data JPA实现分页Pageable的实例代码

    在JPA中提供了很方便的分页功能,那就是Pageable(org.springframework.data.domain.Pageable)以及它的实现类PageRequest(org.springframework.data.domain.PageRequest),详细的可以见示例代码. 1.改变CustomerRepository方法​ /** * 一个参数,匹配两个字段 * @param name2 * @Param pageable 分页参数 * @return * 这里Param的值和

  • 详解spring boot jpa整合QueryDSL来简化复杂操作

    前言 使用过spring data jpa的同学,都很清楚,对于复杂的sql查询,处理起来还是比较复杂的,而本文中的QueryDSL就是用来简化JPA操作的. Querydsl定义了一种常用的静态类型语法,用于在持久域模型数据之上进行查询.JDO和JPA是Querydsl的主要集成技术.本文旨在介绍如何使用Querydsl与JPA组合使用.JPA的Querydsl是JPQL和Criteria查询的替代方法.QueryDSL仅仅是一个通用的查询框架,专注于通过Java API构建类型安全的SQL查

  • SpringBoot Data JPA 关联表查询的方法

    SpringBoot Data JPA实现 一对多.多对一关联表查询 开发环境 IDEA 2017.1 Java1.8 SpringBoot 2.0 MySQL 5.X 功能需求 通过关联关系查询商店Store中所有的商品Shop,商店对商品一对多,商品对商店多对一,外键 store_id存在于多的一方.使用数据库的内连接语句. 表结构 tb_shop tb_store 实体类,通过注解实现 1.商店类Store.java package com.gaolei.Entity; import ja

  • spring jpa ManyToMany原理及用法详解

    1.java和jpa 中所有的关系都是单向的.这个关系数据库不同,关系数据库,通过外键定义并查询,使得反向查询总是存在的. 2.JPA还定义了一个OneToMany关系,它与ManyToMany关系类似,但反向关系(如果已定义)是ManyToOne关系. OneToMany与JPA中ManyToMany关系的主要区别在于,ManyToMany总是使用中间关系连接表来存储关系, OneToMany可以使用连接表或者目标对象的表引用中的外键源对象表的主键. @OneToMany(cascade =

  • Java switch关键字原理及用法详解

    这篇文章主要介绍了Java中 switch关键原理及用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Switch语法 switch作为Java内置关键字,却在项目中真正使用的比较少.关于switch,还是有那么一些奥秘的. 要什么switch,我有if-else 确实,项目中使用switch比较少的一个主要原因就在于它的作用能被if-else代替,况且switch对类型的限制,也阻碍了switch的进一步使用. 先看看switch的语法

  • Spring事务管理原理及方法详解

    这篇文章主要介绍了Spring事务管理原理及方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 事务,在日常开发或者面试中都必定会涉及到.开发工作中,结合数据库开发理解就是:一组dml要么全部成功执行提交,要么因为某一个操作异常,撤销之前所做的成功的操作,整体执行失败.再简单点的一句话:生死与共. 由此,可以看出,事务的必要性:在开发工作中,保证操作数据的安全性.事务的控制也就是保证数据的访问安全性. 一.事务的四大特性 A:原子性(ato

  • Spring MVC 拦截器 interceptor 用法详解

    Spring MVC-拦截器 今天就是把有关拦截器的知识做一个总结. 1.拦截器概述 1.1 什么是拦截器? Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理.例如通过拦截器可以进行权限验证.记录请求信息的日志.判断用户是否登录等. 要使用Spring MVC中的拦截器,就需要对拦截器类进行定义和配置.通常拦截器类可以通过两种方式来定义. 1.通过实现HandlerInterceptor接口,或继承Han

  • python 标准库原理与用法详解之os.path篇

    os中的path 查看源码会看到,在os.py中有这样几行 if 'posix' in _names: name = 'posix' linesep = '\n' from posix import * #省略若干代码 elif 'nt' in _names: from nt import * try: from nt import _exit __all__.append('_exit') except ImportError: pass import ntpath as path #...

  • Java基础之Stream流原理与用法详解

    目录 一.接口设计 二.创建操作 三.中间操作 四.最终操作 五.Collect收集 Stream简化元素计算 一.接口设计 从Java1.8开始提出了Stream流的概念,侧重对于源数据计算能力的封装,并且支持序列与并行两种操作方式:依旧先看核心接口的设计: BaseStream:基础接口,声明了流管理的核心方法: Stream:核心接口,声明了流操作的核心方法,其他接口为指定类型的适配: 基础案例:通过指定元素的值,返回一个序列流,元素的内容是字符串,并转换为Long类型,最终计算求和结果并

  • Spring JPA之save方法示例详解

    目录 一.save(单条添加) 源码 service 层 control层 二.saveAll(批量添加) 源码 service control层 一.save(单条添加) 源码 @Transactional @Override public <S extends T> S save(S entity) { Assert.notNull(entity, "Entity must not be null."); if (entityInformation.isNew(enti

  • Spring的组合注解和元注解原理与用法详解

    本文实例讲述了Spring的组合注解和元注解原理与用法.分享给大家供大家参考,具体如下: 一 点睛 从Spring 2开始,为了相应JDK 1.5推出的注解功能,Spring开始加入注解来替代xml配置.Spring的注解主要用来配置和注入Bean,以及AOP相关配置.随着注解的大量使用,尤其相同的多个注解用到各个类或方法中,会相当繁琐.出现了所谓的样本代码,这是Spring设计要消除的代码. 元注解:可以注解到别的注解上去的注解. 组合注解:被注解的注解,组合注解具备其上的元注解的功能. Sp

  • angular2中Http请求原理与用法详解

    本文实例讲述了angular2中Http请求原理与用法.分享给大家供大家参考,具体如下: 提供HTTP服务 HttpModule并不是Angular的核心模块. 它是Angular用来进行Web访问的一种可选方式,并位于一个名叫@angular/http的独立附属模块中. 编辑app.module.ts import { HttpModule, JsonpModule } from '@angular/http'; @NgModule({ imports: [ HttpModule, Jsonp

  • Java 反射机制原理与用法详解

    本文实例讲述了Java 反射机制原理与用法.分享给大家供大家参考,具体如下: 反射反射,程序员的快乐! 1.什么是反射? Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:并且能改变它的属性.而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是

随机推荐