기술나눔

[Spring Boot] 관계 매핑 개발(3): 다대다 매핑

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

JPA 입문부터 숙련까지》 시리즈에는 다음 기사가 포함됩니다.


존재하다 다수 대 다수 협회 관계에서는 오직중간 테이블 외래 키를 추가하여 매핑을 수행할 수 없습니다.

주석 @다수대수 관계의 송신자와 수신자에 사용됩니다. 관계의 송신측은 컬렉션 유형의 수신측 필드 속성을 정의하며, 관계의 수신측은 어떠한 정의도 필요하지 않습니다.

1. 엔터티 생성

1.1 학생 엔터티 만들기

package com.example.demo.entity;

import lombok.Data;

import javax.persistence.*;
import java.util.List;
import java.util.Set;

@Entity
@Data
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String name;
    @Column(columnDefinition = "enum('male','female')")
    private String sex;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "teacher_student", joinColumns = {@JoinColumn(name = "s_id")}, inverseJoinColumns = {@JoinColumn(name = "t_id")})
    private Set<Teacher> teachers;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

1.2 교사 엔터티 만들기

package com.example.demo.entity;

import lombok.Data;

import javax.persistence.*;
import java.util.List;
import java.util.Set;

@Data
@Entity
public class Teacher {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String name;
    @ManyToMany(fetch = FetchType.LAZY)
    /**
     * Description:
     * 1、关系两边都作为主控;
     * 2、joinColumns 中 @JoinColumn(name="t_id") 其中 t_id 为 JoinTable 中的外键,由于 Student 和 Teacher 的主键都为 id 这边就省略 referencedColumnName="id"。
     */
    @JoinTable(name = "teacher_student", joinColumns = {@JoinColumn(name = "t_id")}, inverseJoinColumns = {@JoinColumn(name = "s_id")})
    private Set<Student> students;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

존재하다 다수 대 다수 관계에서 주의해야 할 사항은 다음과 같습니다.

  • 관계의 양쪽 당사자가 마스터 역할을 할 수 있습니다.
  • 존재하다 joinColumns ~의@JoinColumn(name="t_id") 가운데,t_id JoinTable의 외래 키입니다.Student와 Teacher의 기본 키는 둘 다이므로id이므로 여기서는 생략 referencedColumnName="id"
  • 모델 간의 캐스케이드 관계를 설계할 때 어떤 캐스케이드 규칙을 사용해야 하는지 고려해야 합니다.
  • 설정된 경우 cascade = CascadeType.PERSIST, 그런 다음 실행 save 언제 호출될지onPersist() 방법.이 메서드는 외부 클래스(학생 또는 교사)를 재귀적으로 호출합니다.onPersist() 계단식 추가를 수행합니다.하지만 값이 추가되었기 때문에 보고됩니다.detached entity passed to persist 오류가 발생했습니다. 계단식 작업을 취소하세요(제거cascade = CascadeType.PERSIST).

여기에 이미지 설명을 삽입하세요.

2. 테스트 생성

서비스 및 저장소 계층은 "관계 매핑 개발(1): 일대일 매핑》이미 언급했지만 여기서는 차이가 없으므로 자세한 내용은 생략하고 바로 테스트 레이어의 코드 작성으로 넘어가겠습니다.

package com.example.demo.entity;

import com.example.demo.repository.StudentRepository;
import com.example.demo.repository.TeacherRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.HashSet;
import java.util.Set;

import static org.junit.Assert.*;

@SpringBootTest
@RunWith(SpringRunner.class)
public class ManyToManyTest {
    @Autowired
    private StudentRepository studentRepository;
    @Autowired
    private TeacherRepository teacherRepository;

    @Test
    public void add() {

        Set<Teacher> teachers = new HashSet<>();
        Set<Student> students = new HashSet<>();

        Student student1 = new Student();
        student1.setName("张三");
        students.add(student1);
        studentRepository.save(student1);

        Student student2 = new Student();
        student2.setName("李四");
        students.add(student2);
        studentRepository.save(student2);

        Teacher teacher1 = new Teacher();
        teacher1.setName("皮皮老师");
        teacher1.setStudents(students);
        teachers.add(teacher1);
        teacherRepository.save(teacher1);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

테스트 클래스 실행제어 장치다음 결과가 출력됩니다.

여기에 이미지 설명을 삽입하세요.

여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.

🚀 对于双向 ManyToMany 关系,注解 @ManyToMany 用于关系的发出端和接收端。另外,关系的接收端需要设置 @ManyToMany(mappedBy='集合类型发出端实体的字段名称')