JPA - N:N 연관관계 처리

킹콩(King Kong)·2025년 1월 14일

N:N 연관관계 mappedBy 쪽 데이타가 안보일때

  • N:N 관계에서 연관관계 주인쪽은 하위 데이타가 보이는데,
  • 반대편은 LAZY 로 인해 값이 안보인다.
    • 이때 보이게 하려면 DTO를 사용해서 하위 데이터를 읽어야 한다.

  • SubjectServiceImpl.java
@Service
public class SubjectServiceImpl implements SubjectService {

    @Autowired
    SubjectRepository subjectRepository;


    @Override
    public List<SubjectDTO> findAll() {
        return subjectRepository.findAll().stream()
                .map(this::convertToDTO)
                .collect((Collectors.toList()));
    }

    @Override
    public List<SubjectDTO> findBySubjectNameContainsIgnoreCase(String subjectName) {
        return subjectRepository.findBySubjectNameContainsIgnoreCase(subjectName, Sort.by(Sort.Direction.ASC, "subjectName")).stream()
                .map(this::convertToDTO)
                .collect((Collectors.toList()));
    }

    // Entity -> DTO 변환 메서드
    private SubjectDTO convertToDTO(Subject subject) {
        SubjectDTO dto = new SubjectDTO();
        dto.setId(subject.getId());
        dto.setSubjectName(subject.getSubjectName());
        dto.setMaxScore(subject.getMaxScore());

        // Student 리스트 변환
        List<StudentDTO> students = subject.getStudents().stream()
                .map(student -> {
                    StudentDTO studentDTO = new StudentDTO();
                    studentDTO.setId(student.getId());
                    studentDTO.setStudentName(student.getStudentName());
                    studentDTO.setCellPhone(student.getCellPhone());
                    return studentDTO;
                })
                .collect(Collectors.toList());
        dto.setStudents(students);

        return dto;
    }
}
  • StudentServiceImpl.java
    • student가 연관관계 주인일때, 연관관계 주인쪽은 그냥 읽으면 하위 데이타가 읽혀진다.
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    StudentRepository studentRepository;


    @Override
    public List<Student> findAll() {
        return studentRepository.findAll();
    }

    @Override
    public List<Student> findByStudentNameContainsIgnoreCase(String studentName) {
        return studentRepository.findByStudentNameContainsIgnoreCase(studentName, Sort.by(Sort.Direction.ASC, "studentName"));
    }

}
  • Subject.java
@Entity
@Data
@Table
public class Subject implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "subject_id")
    Long id;
    String subjectName;
    int maxScore;

    @ManyToMany(mappedBy = "subjects", fetch = FetchType.EAGER)
    @JsonBackReference
    private List<Student> students = new ArrayList<>();

    @Override
    public String toString() {
        return "id=" + id + ", subjectName=" + subjectName + ", maxScore=" + maxScore;
    }
}
  • Student.java : 연관관계 주인
@Entity
@Data
@Table
public class Student implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "student_id")
    Long id;
    String studentName;
    String cellPhone;

    @ManyToMany (fetch = FetchType.LAZY)
    @JsonManagedReference
    @JoinTable(name="student_subject",
            joinColumns = @JoinColumn(name="student_id"),
            inverseJoinColumns = @JoinColumn(name = "subject_id"))
    private List<Subject> subjects = new ArrayList<>();

    @Override
    public String toString() {
        return "id=" + id + ", studentName=" + studentName + ", cellPhone=" + cellPhone;
    }
}
  • SubjectRepository.java
public interface SubjectRepository extends JpaRepository<Subject, Long> {

    @Query("SELECT s FROM Subject s JOIN FETCH s.students WHERE UPPER(s.subjectName) LIKE UPPER(CONCAT('%', :subjectName, '%'))")
    List<Subject> findBySubjectNameContainsIgnoreCase(@Param("subjectName") String subjectName, Sort sort);
}
  • StudentRepository.java
public interface StudentRepository extends JpaRepository<Student, Long> {

    @Query("SELECT s FROM Student s JOIN FETCH s.subjects WHERE UPPER(s.studentName) LIKE UPPER(CONCAT('%', :studentName, '%'))")
    List<Student> findByStudentNameContainsIgnoreCase(@Param("studentName") String studentName, Sort sort);
}
profile
IT를 쉽게 이해해 보아요~😄

0개의 댓글