一、@OneToOne关系映射

JPA使用@OneToOne来标注一对一的关系。

实体 People :用户。

实体 Address:家庭住址。

People 和 Address 是一对一的关系。

这里用两种方式描述JPA的一对一关系。

一种是通过外键的方式(一个实体通过外键关联到另一个实体的主键);

另外一种是通过一张关联表来保存两个实体一对一的关系。

1、通过外键的方式

people 表(id,name,sex,birthday,address_id)

address 表(id,phone,zipcode,address)

People.java

  1. @Entity
  2. public class People {
  3. @Id
  4. @GeneratedValue(strategy = GenerationType.IDENTITY)
  5. @Column(name = "id", nullable = false)
  6. private Long id;//id
  7. @Column(name = "name", nullable = true, length = 20)
  8. private String name;//姓名
  9. @Column(name = "sex", nullable = true, length = 1)
  10. private String sex;//性别
  11. @Column(name = "birthday", nullable = true)
  12. private Timestamp birthday;//出生日期
  13. @OneToOne(cascade=CascadeType.ALL)//People是关系的维护端,当删除 people,会级联删除 address
  14. @JoinColumn(name = "address_id", referencedColumnName = "id")//people中的address_id字段参考address表中的id字段
  15. private Address address;//地址
  16. }

关联的实体的主键一般是用来做外键的。但如果此时不想主键作为外键,则需要设置referencedColumnName属性。当然这里关联实体(Address)的主键 id 是用来做主键,所以这里第20行的 referencedColumnName = "id" 实际可以省略。

Address.java

  1. @Entity
  2. public class Address {
  3. @Id
  4. @GeneratedValue(strategy = GenerationType.IDENTITY)
  5. @Column(name = "id", nullable = false)
  6. private Long id;//id
  7. @Column(name = "phone", nullable = true, length = 11)
  8. private String phone;//手机
  9. @Column(name = "zipcode", nullable = true, length = 6)
  10. private String zipcode;//邮政编码
  11. @Column(name = "address", nullable = true, length = 100)
  12. private String address;//地址
  13. //如果不需要根据Address级联查询People,可以注释掉
  14. //    @OneToOne(mappedBy = "address", cascade = {CascadeType.MERGE, CascadeType.REFRESH}, optional = false)
  15. //    private People people;
  16. }

2、通过关联表的方式来保存一对一的关系。

people 表(id,name,sex,birthday)

address 表 (id,phone,zipcode,address)

people_address (people_id,address_id)

只需要创建 People 和 Address 两个实体

People.java

  1. @Entity
  2. public class People {
  3. @Id
  4. @GeneratedValue(strategy = GenerationType.IDENTITY)
  5. @Column(name = "id", nullable = false)
  6. private Long id;//id
  7. @Column(name = "name", nullable = true, length = 20)
  8. private String name;//姓名
  9. @Column(name = "sex", nullable = true, length = 1)
  10. private String sex;//性别
  11. @Column(name = "birthday", nullable = true)
  12. private Timestamp birthday;//出生日期
  13. @OneToOne(cascade=CascadeType.ALL)//People是关系的维护端
  14. @JoinTable(name = "people_address",
  15. joinColumns = @JoinColumn(name="people_id"),
  16. inverseJoinColumns = @JoinColumn(name = "address_id"))//通过关联表保存一对一的关系
  17. private Address address;//地址
  18. }

Address.java

不变

二、@OneToMany 和 @ManyToOne

实体 Author:作者。

实体 Article:文章。

Author 和 Article 是一对多关系(双向)。那么在JPA中,如何表示一对多的双向关联呢?

JPA使用@OneToMany和@ManyToOne来标识一对多的双向关联。一端(Author)使用@OneToMany,多端(Article)使用@ManyToOne。

JPA规范中,一对多的双向关系由多端(Article)来维护。就是说多端(Article)为关系维护端,负责关系的增删改查。一端(Author)则为关系被维护端,不能维护关系。

一端(Author)使用@OneToMany注释的mappedBy="author"属性表明Author是关系被维护端。

多端(Article)使用@ManyToOne和@JoinColumn来注释属性 author,@ManyToOne表明Article是多端,@JoinColumn设置在article表中的关联字段(外键)。

Author.java

  1. @Entity
  2. public class Author {
  3. @Id // 主键
  4. @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略
  5. private Long id; //id
  6. @NotEmpty(message = "姓名不能为空")
  7. @Size(min=2, max=20)
  8. @Column(nullable = false, length = 20)
  9. private String name;//姓名
  10. @OneToMany(mappedBy = "author",cascade=CascadeType.ALL,fetch=FetchType.LAZY)
  11. //级联保存、更新、删除、刷新;延迟加载。当删除用户,会级联删除该用户的所有文章
  12. //拥有mappedBy注解的实体类为关系被维护端
  13. //mappedBy="author"中的author是Article中的author属性
  14. private List<Article> articleList;//文章列表
  15. }

Article.java

  1. @Entity
  2. public class Article {
  3. @Id
  4. @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增长策略
  5. @Column(name = "id", nullable = false)
  6. private Long id;
  7. @NotEmpty(message = "标题不能为空")
  8. @Size(min = 2, max = 50)
  9. @Column(nullable = false, length = 50) // 映射为字段,值不能为空
  10. private String title;
  11. @Lob  // 大对象,映射 MySQL 的 Long Text 类型
  12. @Basic(fetch = FetchType.LAZY) // 懒加载
  13. @NotEmpty(message = "内容不能为空")
  14. @Size(min = 2)
  15. @Column(nullable = false) // 映射为字段,值不能为空
  16. private String content;//文章全文内容
  17. @ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},optional=false)//可选属性optional=false,表示author不能为空。删除文章,不影响用户
  18. @JoinColumn(name="author_id")//设置在article表中的关联字段(外键)
  19. private Author author;//所属作者
  20. }

最终生成的表结构

article 表(id,title,conten,author_id)

author 表(id,name)

三、多对多 @ManyToMany

实体 User:用户。

实体 Authority:权限。

用户和权限是多对多的关系。一个用户可以有多个权限,一个权限也可以被很多用户拥有。

JPA中使用@ManyToMany来注解多对多的关系,由一个关联表来维护。这个关联表的表名默认是:主表名+下划线+从表名。(主表是指关系维护端对应的表,从表指关系被维护端对应的表)。这个关联表只有两个外键字段,分别指向主表ID和从表ID。字段的名称默认为:主表名+下划线+主表中的主键列名,从表名+下划线+从表中的主键列名。

需要注意的:

1、多对多关系中一般不设置级联保存、级联删除、级联更新等操作。

2、可以随意指定一方为关系维护端,在这个例子中,我指定 User 为关系维护端,所以生成的关联表名称为: user_authority,关联表的字段为:user_id 和 authority_id。

3、多对多关系的绑定由关系维护端来完成,即由 User.setAuthorities(authorities) 来绑定多对多的关系。关系被维护端不能绑定关系,即Game不能绑定关系。

4、多对多关系的解除由关系维护端来完成,即由Player.getGames().remove(game)来解除多对多的关系。关系被维护端不能解除关系,即Game不能解除关系。

5、如果 User 和 Authority 已经绑定了多对多的关系,那么不能直接删除 Authority,需要由 User 解除关系后,才能删除 Authority。但是可以直接删除 User,因为 User 是关系维护端,删除 User 时,会先解除 User 和 Authority 的关系,再删除 Authority。

User.java

  1. @Entity
  2. public class User {
  3. @Id
  4. @GeneratedValue(strategy = GenerationType.IDENTITY)
  5. private Long id;
  6. @NotEmpty(message = "账号不能为空")
  7. @Size(min=3, max=20)
  8. @Column(nullable = false, length = 20, unique = true)
  9. private String username; // 用户账号,用户登录时的唯一标识
  10. @NotEmpty(message = "密码不能为空")
  11. @Size(max=100)
  12. @Column(length = 100)
  13. private String password; // 登录时密码
  14. @ManyToMany
  15. @JoinTable(name = "user_authority",joinColumns = @JoinColumn(name = "user_id"),
  16. inverseJoinColumns = @JoinColumn(name = "authority_id"))
  17. //1、关系维护端,负责多对多关系的绑定和解除
  18. //2、@JoinTable注解的name属性指定关联表的名字,joinColumns指定外键的名字,关联到关系维护端(User)
  19. //3、inverseJoinColumns指定外键的名字,要关联的关系被维护端(Authority)
  20. //4、其实可以不使用@JoinTable注解,默认生成的关联表名称为主表表名+下划线+从表表名,
  21. //即表名为user_authority
  22. //关联到主表的外键名:主表名+下划线+主表中的主键列名,即user_id
  23. //关联到从表的外键名:主表中用于关联的属性名+下划线+从表的主键列名,即authority_id
  24. //主表就是关系维护端对应的表,从表就是关系被维护端对应的表
  25. private List<Authority> authorityList;
  26. }

注意:如注释中所言,上面的第20-21行的@JoinTable可以省略,默认可以生成

Authority.java

  1. @Entity
  2. public class Authority {
  3. @Id
  4. @GeneratedValue(strategy = GenerationType.IDENTITY)
  5. private Integer id;
  6. @Column(nullable = false)
  7. private String name; //权限名
  8. @ManyToMany(mappedBy = "authorityList")
  9. private List<User> userList;
  10. }

关于JPA一对一,一对多(多对一),多对多的详解的更多相关文章

  1. JPA 一对一 一对多 多对一 多对多配置

    1 JPA概述 1.1 JPA是什么 JPA (Java Persistence API) Java持久化API.是一套Sun公司 Java官方制定的ORM 方案,是规范,是标准 ,sun公司自己并没 ...

  2. JPA级联(一对一 一对多 多对多)注解【实际项目中摘取的】并非自己实际应用

    下面把项目中的用户类中有个:一对一  一对多  多对多的注解对应关系列取出来用于学习      说明:项目运行正常 问题类:一对多.一对一.多对多 ============一对多 一方的设置 @One ...

  3. JPA的一对多,多对多用法

    一.@OneToOne关系映射 JPA使用@OneToOne来标注一对一的关系. 实体 People :用户. 实体 Address:家庭住址. People 和 Address 是一对一的关系. 这 ...

  4. Django ORM、一对一、一对多、多对多、详解

    上篇博客也提到这些知识点,可能大家还是不太清楚,这篇博客为大家详细讲解ORM中的几个知识点 1.1首先我们先看一个小案例: #_*_coding:utf-8_*_ from django.db imp ...

  5. mybatis 详解(七)------一对一、一对多、多对多

    前面几篇博客我们用mybatis能对单表进行增删改查操作了,也能用动态SQL书写比较复杂的sql语句.但是在实际开发中,我们做项目不可能只是单表操作,往往会涉及到多张表之间的关联操作.那么我们如何用 ...

  6. 初学者易上手的SSH-hibernate04 一对一 一对多 多对多

    这章我们就来学习下hibernate的关系关联,即一对一(one-to-one),一对多(one-to-many),多对多(many-to-many).这章也将是hibernate的最后一章了,用于初 ...

  7. day 69-70 一对一 一对多 多对一联表查询

    day 69 orm操作之表关系,多对多,多对一 多对一/一对多, 多对多{类中的定义方法} day69 1. 昨日内容回顾 1. 单表增删改查 2. 单表查询API 返回QuerySet对象的: 1 ...

  8. mybatis 一对多,(多对一,一对一

    多对一,和一对一是同一种写法,每种写法又分在数据库关联和在mybatis关联 1,多对一,一对一数据库关联 2,多对一,一对一mybatis关联 3,一对多,数据库关联,注意,Java type改of ...

  9. JPA实体关系映射:@ManyToMany多对多关系、@OneToMany@ManyToOne一对多多对一关系和@OneToOne的深度实例解析

    JPA实体关系映射:@ManyToMany多对多关系.@OneToMany@ManyToOne一对多多对一关系和@OneToOne的深度实例解析 今天程序中遇到的错误一 org.hibernate.A ...

随机推荐

  1. net core 微服务 快速开发框架

    dymDemo github 地址:https://github.com/duyanming/dymDemo dym 分布式开发框架 Demo 熔断 限流 事件总线(包括基于内存的.rabbitmq的 ...

  2. linux(centos8):awk在系统运维中的常用例子

    一,awk的作用 1,用途 AWK是一种处理文本文件的语言, 是一个强大的文本分析工具 2,awk和sed的区别 awk适合按列(域)操作, sed适合按行操作 awk适合对文件的读取分析, sed适 ...

  3. 往with as中写入数据的方法

    方法1:直接写入,使用union all,简单直观,但程序运行效率低,几百条就很慢了 with dw_wms_outbound_info_v100 as( select '10700001' as o ...

  4. 详解GaussDB(DWS) explain分布式执行计划

    摘要:本文主要介绍如何详细解读GaussDB(DWS)产生的分布式执行计划,从计划中发现性能调优点. 前言 执行计划(又称解释计划)是数据库执行SQL语句的具体步骤,例如通过索引还是全表扫描访问表中的 ...

  5. 天猫精灵对接2(OAuth 搭建)

    根据 接入方式及流程 中的说明,可知,搭建过程中,我们需要自己整一个 OAuth 的授权平台,具体说明可以参考蟋蟀大哥的文章  ASP.NET WebApi OWIN 实现 OAuth 2.0 ,我的 ...

  6. java之集合容器(Collection,Map)

    首先我们要了解什么是集合? 正所谓容器,比如说杯子是装水的容器,衣柜是装衣服的容器,那么集合就是装数据的容器. 集合有什么特点呢? 1.集合长度是可变的 2.集合用来存储对象 集合和数组有什么区别呢? ...

  7. APP后台架构20191205

    1.架构,架构与业务紧密相关,是有业务驱动的. 2.APP后台演进原则. App后台的架构是由业务规模驱动而演进的,App后台是为业务服务的,App后台的价值在于能为业务提供其所需要的功能,不应过度设 ...

  8. 如何計算n個圓的聯集面積

    如何計算n個圓的聯集面積 前言 一般人第一次遇到這個問題,可能會想要想辦法用排容原理,找圓之間交疊的凸包之類的.... 然而我只要舉一個例子,你就會發現我們就算把凸包找出來了,我們也非常難知道找到的凸 ...

  9. 【总结】vertica数据库

    1.简介 Vertica是一款基于列式存储架构的数据库,可以支持存放多至PB级别的结构化数据 2.列式存储 行式存储就是以行为单位进行存储,再配合B+树作为索引,就能快速通过主键找到相应的行数据.即大 ...

  10. Luogu P4957 [COCI2017-2018#6] Alkemija

    题意 有 \(n\) 种已知物质,现在手上有 \(m\) 种,每种无限多个.已知 \(k\) 种反应,每种可以将一些反应物变成一些生成物.求经过这些反应过后最多可以有多少种不同的物质. \(\text ...