8、JPA对象关系-双向多对多 @JoinTable

JPA对象关系-双向多对多

关系型数据库设计时,多对多关系一般会创建1个中间表维护关系,类似JPA 一对多时,默认生成1个中间表维护关系。
单向多对多和单向一对多其实是一样的,都会生成1个中间表维护关系。不在详细说明,这里主要说一下双向多对多
下面部门和员工为例,1个部门可以有多个员工,同理1个员工可以在多个部门任职。
在这里插入图片描述

1、类型定义

@Data
@Entity
public class Department {
    @Id
    @GeneratedValue
    private long id;
    private String name;

    @ManyToMany
    public List<Employee> employees;
}

@Data
@Entity
public class Employee {
    @Id
    @GeneratedValue
    private long id;
    private String name;

    @ManyToMany
    private List<Department> departments;
}

2、测试保存

@Test
    public void save(){
        Department d1=new Department();
        d1.setName("财务部");
        Department d2=new Department();
        d2.setName("人事部");

        Employee gg=new Employee();
        gg.setName("gg");
        Employee jl=new Employee();
        jl.setName("jl");

        //设置关系
        List<Employee> employees=new ArrayList<>();
        employees.add(gg);
        employees.add(jl);
        d1.setEmployees(employees);
        d2.setEmployees(employees);

        List<Department> departments=new ArrayList<>();
        departments.add(d1);
        departments.add(d2);
        gg.setDepartments(departments);
        jl.setDepartments(departments);

        //保存
        EntityManager entityManager = JpaUtil.getEntityManager();
        entityManager.getTransaction().begin();

        entityManager.persist(d1);
        entityManager.persist(d2);
        entityManager.persist(gg);
        entityManager.persist(jl);

        entityManager.getTransaction().commit();
        entityManager.close();

    }

3、控制台SQL打印输出

发现打印的SQL,在保存部门和员工后,保存关系时,向2个关系表都插入了数据。JPA默认每个对象上的@ManyToMany 都会生成一个关系表,各自维护各自的关系表。此时我们需要让1方放弃关系维护。

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name) values (?)
Hibernate: insert into Employee (name) values (?)
Hibernate: insert into Department_Employee (Department_id, employees_id) values (?, ?)
Hibernate: insert into Department_Employee (Department_id, employees_id) values (?, ?)
Hibernate: insert into Department_Employee (Department_id, employees_id) values (?, ?)
Hibernate: insert into Department_Employee (Department_id, employees_id) values (?, ?)
Hibernate: insert into Employee_Department (Employee_id, departments_id) values (?, ?)
Hibernate: insert into Employee_Department (Employee_id, departments_id) values (?, ?)
Hibernate: insert into Employee_Department (Employee_id, departments_id) values (?, ?)
Hibernate: insert into Employee_Department (Employee_id, departments_id) values (?, ?)

在这里插入图片描述

4、解决双向多对多2个关系表问题 mappedBy

随便让1方放弃关系维护,这里让员工对象mappedBy放弃关系维护,如下代码。

@Data
@Entity
public class Employee {
    @Id
    @GeneratedValue
    private long id;
    private String name;

    //放弃关系维护
    @ManyToMany(mappedBy = "employees")
    private List<Department> departments;
}

@Data
@Entity
public class Department {
    @Id
    @GeneratedValue
    private long id;
    private String name;

    @ManyToMany
    public List<Employee> employees;
}

在这里插入图片描述

双向多对多关系时,如何手动维护关系 @JoinTable

直接@ManyToMany JPA 默认会生成一个关系表,维护关系,但是大部分情况下,中间关系表都是手动创建的,如何不让JPA默认生成关系表呢?用@JoinTable指定关系表,关系表每个列与外键表的哪个列进行对应。另外一方同样放弃关系维护即可。

@Data
@Entity
public class Department {
    @Id
    @GeneratedValue
    private long id;
    private String name;

    //@JoinTable 多对多关系,name 指定中间表名称
    //joinColumns 指定当前对象哪个列referencedColumnName,和中间表哪个列name对应
    //inverseJoinColumns 指定依赖对象,哪个列referencedColumnName,和中间表哪个列name对应
    @ManyToMany
    @JoinTable(name = "Department_Employee",
    joinColumns = @JoinColumn(name = "departments_id",referencedColumnName = "id")
    ,inverseJoinColumns = @JoinColumn(name = "employees_id",referencedColumnName = "id"))
    public List<Employee> employees;
}

@Data
@Entity
public class Employee {
    @Id
    @GeneratedValue
    private long id;
    private String name;

    //放弃关系维护
    @ManyToMany(mappedBy = "employees")
    private List<Department> departments;
}

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值