[Spring] JPA + MySQL (M:N, 다대다 관계)

진주·2022년 3월 23일
0

Spring

목록 보기
25/29

프로젝트 생성

다대일 N:1관계 때 사용한 jpa2 폴더 복사 붙인 후, 폴더명 jpa3으로 변경

AppTest.java에서 testSave()만 남겨두기


persistence.xml에서
1) value = "update"가 아닌 create로 되어있는지 확인해야함

2) 프로젝트 명 jpa2에서 jpa3로 바꾸기


AppTest.java의 testSave()에서 Persistence.createEntityManagerFactory("jpa3");으로 되어있는지 확인

STUDENT, MAJOR TABLE에 DATA가 제대로 추가됐다!


MAJOR에서도 STUDENT가 조회할 수 있도록 설정하기 (객체 지향 코드, 다대다 관계)

객체 지향 코드는 MAJOR에서 STUDENT TABLE 필드가 없어서 조회할 수 없었다.

Major.java 코드 추가

  // OneToMany : Major입장에서는 전공 1개당 여러명의 student(Many)가 존재
  // OneTomany가 없어도 @JoinColumn으로 인해 SQL문에서는 양쪽 모두 조회가 가능하지만, 객체지향 코드에서는 major에서 student를 조회할 수 없다.
  // mappedBy = "major"로 인해 외래키를 설정했다. = 연관 관계를 주입?했다
  // N:1에서 N 쪽이 주인이 된다. 
  @OneToMany(mappedBy = "major") 
  // Student.java의 Major 'major'필드를 지정. 반대쪽 매핑의 필드 이름을 설정
  private List<Student> students = new ArrayList<>();

  public List<Student> getStudents() {
    return students;
  }

  public void setStudents(List<Student> students) {
    this.students = students;
  }

AppTest.java - readStudents()

    // JPA를 활용하여 STUDENT LIST 조회하기
    @Test
    public void readStudents(){
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa3");
        EntityManager em = emf.createEntityManager();

        // EntityTransaction tx = em.getTransaction(); 조회할 때는 tx 필요 X
        Major major = em.find(Major.class, 1L);
        List<Student> students = major.getStudents();
        
        for(Student student : students){
            System.out.println(student.getStudentName());
        }
    }

persistence.xml에서 update로 변경 후 @Test readStudents() 실행

디버그 콘솔에 김나나, 김빵빵 출력됐다.


testSaveNonOwnerWithJPA()

@Test
    public void testSaveNonOwnerWithJPA(){
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa3");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        Major major1 = new Major("통계학과");
        em.persist(major1);

        Student student1 = new Student("강우리");
        Student student2 = new Student("송진희");

        // student1.setMajor(major1); : 원래는 이렇게 해야하는데
        // 연관 관계의 주인은 N : 1 에서 N(Student.java)에 해당한다.
        
        // 🤔 연관 관계의 주인이 아닌 M(Major)에만 연관 관계를 설정할 경우 ??? 
        // 즉, student1.setMajor(major1); 를 설정하지 않은상태
        major1.getStudents().add(student1); // 🤔?
        major1.getStudents().add(student2);	// 🤔?

        em.persist(student1);
        em.persist(student2);
        

        tx.commit();

    }

create로 변경

실행은 제대로 됐지만,

MAJOR_ID가 NULL이 들어갔다!!


testSaveOwnerOnlyWithOOP() - 객체지향 코드로 연관 관계의 주인(Student)에만 연관 관계를 설정한 경우

즉, major1.getStudents().add(student1); 코드가 없음!!

    @Test
    public void testSaveOwnerOnlyWithOOP(){
        // OOP = 순수한 객체 지향 코드로만 설정
        Major major1 = new Major("통계학과");

        Student student1 = new Student("강우리");
        student1.setMajor(major1);
        // major1.getStudents().add(student1);  코드가 없음!!
        
        Student student2 = new Student("송진희");
        student2.setMajor(major1);

        List<Student> students = major1.getStudents();
        System.out.println("students.size : " + students.size());

    }

size : 0이 출력된다 !!! (오류인 상황)


biWithOOP() - 순수 객체 지향 코드에서 양방향 맵핑 적용한 경우

        @Test
    public void biWithOOP(){    // 순수 객체 지향적인 양방향 맵핑 적용 결과
        // 학과
        Major major1 = new Major("수학과");

        Student student1 = new Student("강우리");
        Student student2 = new Student("송진희");

        student1.setMajor(major1);          // 연관관계 주인 맵핑
        student2.setMajor(major1);
        
        major1.getStudents().add(student1); // 반대편 연관 관계 팹핑
        major1.getStudents().add(student2);
        
        List<Student> students = major1.getStudents();
        System.out.println("student.size : " + students.size()); // 2
    }

size : 2 로 정확하게 출력됐다!


biWithJPA() - JPA를 적용한 양방향 맵핑

    @Test
    public void biWithJPA(){
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa3");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        Major major1 = new Major("수학과");
        em.persist(major1);

        Student student1 = new Student("강우리");
        Student student2 = new Student("송진희");

        // 양방향 연관 관계 설정하기
        student1.setMajor(major1);          // 연관관계 주인 맵핑
        student2.setMajor(major1);

        major1.getStudents().add(student1); // 반대편 연관 관계 팹핑
        major1.getStudents().add(student2);
        
        // 영속성 컨텍스트에 영속화
        em.persist(student1);
        em.persist(student2);

        // 확인을 위해 JOIN문을 사용해야한다던데..
        // SELECT S.*, M.MAJOR_FILED FROM STUDENT S JOIN MAJOR M ON S.MAJOR_ID = M.MAJOR_ID WHERE S.MAJOR_ID = 1;
        tx.commit();
    }

JOIN문 사용하여 MAJOR_FIELD를 확인할 수 있다.

SELECT S.*, M.MAJOR_FILED FROM STUDENT S JOIN MAJOR M ON S.MAJOR_ID = M.MAJOR_ID WHERE S.MAJOR_ID = 1;

profile
진주의 코딩일기

0개의 댓글