• Spring boot data JPA数据库映射关系 : @OneToOne,@OneToMany,@ManyToMany


    问题描述

    在利用Spring boot data JPA进行表设计的时候,表对象之间经常存在各种映射关系,如何正确将理解的映射关系转化为代码中的映射关系是关键之处。

    解决办法

    概念理解

    • 举例:在公司的权限管理中,存在公司表、部门表、员工表。

      1. 公司表和部门表的关系:
        主控方:部门表
        被控方:公司表
      2. 部门表和员工表的关系:
        由于是多对多的关系,不存在谁是主控方或被控方,两者处于平行关系。
    • 一对多或多对一,用外键关联,若未设置级联删除,则删除被控方记录的时候会有外键约束。

    • 多对多,用中间表关联,删除中间表的记录,不会各方的表造成影响。
    • 在该四个注解中,都含有属性可设置,以下举例两个属性。
      1. fetch=FetchType.LAZY为默认的数据延迟加载,fetch=FetchType.EAGER为急加载。
      2. cascade={CascadeType.PERSIST,CascadeType.MERGE,
        CascadeType.REFRESH,CascadeType.REMOVE}.
        其中:
        CascadeType.PERSIST级联新增(又称级联保存);
        CascadeType.MERGE:级联合并(级联更新);
        CascadeType.REMOVE:级联删除;
        CascadeType.REFRESH:级联刷新
        CascadeType.ALL:以上四种都是;
        一般采用CascadeType.MERGE:级联合并(级联更新)即可。默认值是均不进行关联。

    @OneToOne

    • 在一对一的关系中,只需在主控方(数据总表)内注明@OneToOne,而被控方(员工表)只是作为外键,不需任何特殊标记。
    @Entity
    @Table(name = "costume_all_id")
    public class AllId extends AbstractEntity {
        private static final long serialVersionUID = 1L;
    
        @OneToOne(cascade = CascadeType.ALL)
        @JoinColumn(name = "costume_member_fk")
        private Member member;// 用户表外键
    }

    @OneToMany和@ManyToOne

    • 公司(组织)表相对于部门表是被控方,只需在被控方写mappedBy,其值为主控方中引用的外键对象的名称。
    @Entity
    @Table(name = "costume_organization")
    public class Organization extends AbstractEntity {
        private static final long serialVersionUID = 1L;
    
        @Column(nullable = false, length = 50)
        private String name; // 组织名称
    
        @OneToMany(mappedBy = "organization")
        private Set<Department> departmentSet; // 部门集合
    }
    • 部门表相对于公司(组织)表是主控方,在主控方只需写@ManyToOne即可,其对象名为被控表中mappedBy中的值。
    • 同时需要注意,如果需要将公司表对象或者部门表对象转为JSON数据的时候,为了防止出现无限循环包含对方,需要在部门表(多的一方)的引用公司表(少的一方)对象的set方法上写上注解@JsonBackReference
    @Entity
    @Table(name = "costume_department")
    public class Department extends AbstractEntity {
        private static final long serialVersionUID = 1L;
    
        @Column(nullable = false, length = 50)
        private String name; // 部门名称
    
        @ManyToOne(optional = false)
        private Organization organization; // 组织外键
    
        @ManyToMany
        private Set<Member> memberSet; // 用户表外键
    
        public Organization getOrganization() {
            return organization;
        }
    
        @JsonBackReference
        public void setOrganization(Organization organization) {
            this.organization = organization;
        }
    }

    @ManyToMany

    • 在多对多的情况下,如部门表和员工表之间的关系(暂不去深究一个员工是否能有多个部门的身份)。
    • 部门表和员工表只需在引用对象集合上注明@ManyToMany即可,其中部门表的写法如上段代码,员工表的写法如下段代码。
    • 在多对多的映射中会生成一张中间表,其表名和字段名均有默认的命名规则,若需指定表名和字段名,只需在两者的一方或双方写上@JoinTable注解即可,详情如下代码段,表名属性name=”table_name”,与joinColumns属性是同级属性,即写在其前即可。
    • 同时需要注意,如果需要将员工表对象或者部门表对象转为JSON数据的时候,为了防止出现无限循环包含对方,需要在一方的引用对方对象的set方法(Set对象的set方法)上写上注解@JsonBackReference
    @Entity
    @Table(name = "costume_member")
    public class Member extends AbstractEntity {
        private static final long serialVersionUID = 1L;
    
        @Column(nullable = false, length = 20)
        private String name;
    
        @ManyToMany
        @JoinTable(joinColumns = { @JoinColumn(name = "member_id") }, inverseJoinColumns = {
                @JoinColumn(name = "department_id") }) //被控方表字段名
        private Set<Department> departmentSet; // 部门表外键
    
        public Set<Department> getDepartmentSet() {
            return departmentSet;
        }
    
        @JsonBackReference
        public void setDepartmentSet(Set<Department> departmentSet)
        {
            this.departmentSet = departmentSet;
        }
    }
  • 相关阅读:
    网页中嵌入百度地图
    第一篇博客, 感谢博客园
    Flask-Migrate插件
    基于airtest-selenium的UI自动化测试
    自动化测试中如何解决图片验证码问题
    Linux下搭建自动化测试环境
    python3中使用subprocess模块执行外部命令
    微信小程序自动化实战(一)
    python3中使用objectpath模块处理Json对象
    Pytest中如何解决测试用例的依赖执行问题
  • 原文地址:https://www.cnblogs.com/jpfss/p/10894646.html
Copyright © 2020-2023  润新知