작성
·
676
·
수정됨
0
2개의 다대다 관계의 엔티티를 연결테이블을 이용해서 총 3개의 엔티티로 구성했습니다.
Companion 엔티티
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
@AllArgsConstructor
public class Companion {
// Companion 엔티티는 동반 여행에 참여하는 개별 동반자의 정보를 나타냅니다.
// 회원들과의 다대다 관계를 통해 여러 회원과 연결될 수 있으며, 동반 여행의 세부 정보를 저장합니다.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // 동반자 엔티티의 고유 식별자
private String name; // 동반자의 이름
private String code; // 동반자를 구분하는 코드 정보
private Boolean isStart; // 동반 여행의 시작 여부
private Boolean isEnd; // 동반 여행의 종료 여부
private String tendency; // 동반자의 특성 정보
private String mate; // 동반자에 대한 추가 정보
private LocalDateTime startTime; // 동반 여행의 시작 시간
private LocalDateTime endTime; // 동반 여행의 종료 시간
@OneToMany(mappedBy = "companion")
private List<MemberCompanion> companionMembers = new ArrayList<>();
}
Member 엔티티
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Member {
// Member 엔티티는 시스템 사용자를 나타내며, 동반자와의 다대다 관계를 허용합니다.
// 각 회원은 여러 개의 동반자와 연결될 수 있으며, 동반자 정보를 관리합니다.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // 회원 엔티티의 고유 식별자
@Column(unique = true)
private String email; // 회원의 고유한 이메일 주소
private String nickname; // 회원의 사용자명
private String snsType; // 소셜 로그인 종류
private String originalId; // 고유 아이디
@OneToMany(mappedBy = "member")
private List<MemberCompanion> myCompanions = new ArrayList<>();
}
Companion과 Member를 연결하는 Entity
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class MemberCompanion {
// MemberCompanion 엔티티는 회원과 동반자 간의 관계를 정의하는 엔티티입니다.
// 회원과 동반자를 관련시키며, 회원-동반자 관계의 역할 정보를 포함합니다.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // 회원-동반자 관계 엔티티의 고유 식별자
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member; // 회원
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "companion_id")
private Companion companion; // 그룹
@Enumerated(value = EnumType.STRING)
private Role role; // 회원-동반자 관계 역할 (예: 리더, 구성원)
}
문제가 발생한 것은, Companion을 build하고 생성된 Companion과 Member를 통해서 MemberCompanion을 생성한 후, 생성된 MemberCompanion을 다시 Companion의 companionMembers에 넣으려고하면 순환 참조 오류가 터집니다. Dto를 사용해봤지만 잘 해결이 안되어서 질문 올립니다.
/**
* 그룹 등록을 처리하는 메서드
*
* @param companionAddRequestDto 그룹 등록 요청 DTO
* @return ResponseEntity 객체를 반환하여 등록 성공 또는 실패 응답을 전송
*/
@Transactional
public ResponseEntity registCompanion(CompanionAddRequestDto companionAddRequestDto) {
Member member = memberRepository.findById(companionAddRequestDto.getMemberId())
.orElseThrow(() -> new EntityNotFoundException("회원을 찾을 수 없습니다."));
Companion companion = Companion.builder()
.name(companionAddRequestDto.getName())
.code(generateRandomCode())
.isStart(companionAddRequestDto.getIsStart())
.isEnd(companionAddRequestDto.getIsEnd())
.tendency(companionAddRequestDto.getTendency())
.mate(companionAddRequestDto.getMate())
.startTime(companionAddRequestDto.getStartTime())
.endTime(companionAddRequestDto.getEndTime())
.companionMembers(new ArrayList<>())
.build();
companionRepository.save(companion);
// MemberCompanion 엔티티를 생성
MemberCompanion memberCompanion = MemberCompanion.builder()
.member(member)
.companion(companion)
.role(Role.LEADER)
.build();
memberCompanionRepository.save(memberCompanion);
// 등록 성공 응답을 생성하고 반환
return ResponseEntity.ok()
.body(new SuccessResponseDto(true, "그룹 등록이 완료되었습니다.", companion));
}
해당 코드에서
memberCompanionRepository.save(memberCompanion);
이후 companion.getCompanionMembers.add(memberCompanion)시 getCompanionMembers값이 null이라 나오고 다른 방법을 사용하면 순환참조가 발생합니다.
해결 방법이 있을까요..?
답변 1
0
안녕하세요 Hine 님, 인프런 AI 인턴이에요.
순환 참조 오류는 JPA의 양방향 관계 설정으로 인해 발생할 수 있습니다. 현재의 코드에서는 Companion
와 Member
엔티티의 다대다 관계를 MemberCompanion
엔티티를 중간에 두어 관리하고 있습니다. 이 경우 엔티티들 간의 관계 설정을 조금 수정해야 순환 참조 오류를 해결할 수 있습니다.
먼저, MemberCompanion
엔티티에서 Companion
엔티티와 Member
엔티티의 참조 관계를 mappedBy
옵션을 사용하여 연결하고 있습니다. 이 때, mappedBy
는 연관 관계의 주인(Owner)을 설정하는 것으로, 여기서는 MemberCompanion
엔티티의 관계가 주인입니다.
따라서 MemberCompanion
엔티티에서 Companion
엔티티와 Member
엔티티의 참조 관계 설정을 수정해주세요. 예를 들어, MemberCompanion
에서 Companion
을 참조하는 필드명을 memberCompanion
으로 변경하고 Member
에서 MemberCompanion
을 참조하는 필드명을 myCompanionMembers
로 변경할 수 있습니다.
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class MemberCompanion {
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member; // 회원
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "companion_id")
private Companion memberCompanion; // 그룹
...
}
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Member {
...
@OneToMany(mappedBy = "member")
private List<MemberCompanion> myCompanionMembers = new ArrayList<>();
...
}
이후, Companion
엔티티의 companionMembers
필드에서 mappedBy 옵션을 추가해야 합니다. 이렇게 하면 Companion
엔티티가 MemberCompanion
엔티티를 참조하게 됩니다.
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
@AllArgsConstructor
public class Companion {
...
@OneToMany(mappedBy = "memberCompanion")
private List<MemberCompanion> companionMembers = new ArrayList<>();
...
}
이렇게 수정 후에는 순환 참조 오류가 발생하지 않도록 할 수 있습니다. 변경 후에는 관련된 필드들의 접근 방식과 데이터의 설정 등도 확인해보시기 바랍니다. 이렇게 수정한 뒤에는 해당 오류가 해결되었는지 확인해보세요. 문제가 지속된다면 추가적인 정보를 제공해주시면 더 자세한 도움을 드릴 수 있을 것입니다. 감사합니다.