Spring Data JPA 关系映射(一对一,一对多)

一、@OneToOne关系映射

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

实体 People :用户。

实体 Address:家庭住址。

People 和 Address 是一对一的关系。

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

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

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

1、通过外键的方式

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

address 表(id,phone,zipcode,address)

People.java

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

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

Address.java

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

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

people 表(id,name,sex,birthday)

address 表 (id,phone,zipcode,address)

people_address (people_id,address_id)

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

People.java

    @Entity
    @Data
    public class People {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id", nullable = false)
        private Long id;//id
        @Column(name = "name", nullable = true, length = 20)
        private String name;//姓名
        @Column(name = "sex", nullable = true, length = 1)
        private String sex;//性别
        @Column(name = "birthday", nullable = true)
        private Timestamp birthday;//出生日期
        @OneToOne(cascade=CascadeType.ALL)//People是关系的维护端
        @JoinTable(name = "people_address",
                joinColumns = @JoinColumn(name="people_id"),
                inverseJoinColumns = @JoinColumn(name = "address_id"))//通过关联表保存一对一的关系
        private Address address;//地址
    }
Address.java

不变

二、@OneToMany

实体 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

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

Article.java

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

最终生成的表结构

article 表(id,title,conten,author_id)

author 表(id,name)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值