💻문제점
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_id")
private Long id;
@Column(nullable = false)
private String userId;
@Column(nullable = false)
private String password;
@Column(nullable = false)
private String email;
@Column(nullable = false)
private String nickname;
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private JobEnum job;
@OneToOne(mappedBy = "member", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JsonManagedReference
private Profile profile;
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private List<JoinChatRoom> joinChatRooms = new ArrayList<>();
@Builder
public Member(String userId, String password, String email, String nickname, JobEnum job) {
this.userId = userId;
this.password = password;
this.email = email;
this.nickname = nickname;
this.job = job;
}
public void addChatRoom(JoinChatRoom joinChatRoom) {
this.joinChatRooms.add(joinChatRoom);
}
}
//채팅방 생성
public ResponseDto createChatRoom(String receiver, Member member) {
ChatRoom chatRoom = new ChatRoom(receiver);
JoinChatRoom joinChatRoom = new JoinChatRoom(member, chatRoom);
member.addChatRoom(joinChatRoom);
chatRoomRepository.save(chatRoom);
return ResponseDto.setSuccess("create chatRoom success", chatRoom);
}
채팅방을 생성해 사용자가 참여한 채팅방을 joinChatRooms에 add 하려고 했다.
이때 joinChatRooms는 Member와 ChatRoom의 중간 테이블이며, Member와 ChatRoom은 양방향 연관 관계이다.
그런데 문제가 발생
PostMan을 통해 다음과 같이 요청을 했다.
그리고 콘솔에 발생한 에러
failed to lazily initialize a collection of role: edit.edit.entity.Member.joinChatRooms: could not initialize proxy - no Session
at org.hibernate.collection.spi.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:635) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
at org.hibernate.collection.spi.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
at org.hibernate.collection.spi.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:615) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
at org.hibernate.collection.spi.AbstractPersistentCollection.write(AbstractPersistentCollection.java:442) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
at org.hibernate.collection.spi.PersistentBag.add(PersistentBag.java:385) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
📃시도
찾아보다가 '사용할 때 영속성 컨텍스트가 종료되어서 지연 로딩을 할 수 없어 발생하는 오류' 라는 말에 해당 메서드에 트랜잭션이 잘 되어있는지 확인해보았다. 클래스에 @Transactional을 붙인 상태라 해당 문제는 아닌 것으로 판단...
@Service
@Slf4j
@RequiredArgsConstructor
@Transactional
public class ChatService {
private final ChatRoomRepository chatRoomRepository;
/**
* 채팅방 생성
*/
public ResponseDto createChatRoom(String receiver, Member member) {
ChatRoom chatRoom = new ChatRoom(receiver);
JoinChatRoom joinChatRoom = new JoinChatRoom(member, chatRoom);
member.addChatRoom(joinChatRoom);
chatRoomRepository.save(chatRoom);
return ResponseDto.setSuccess("create chatRoom success", chatRoom);
}
/* ... */
}
🔍해결
지연 로딩으로 인해 생성된 프록시 객체를 초기화 하지 못한 것. 즉 연관 데이터를 가져오는 것에 실패한 것이다.
fetch 타입은 EAGER로 바꾸어 Member 조회시 연관된 데이터를 함께 가져오도록 하였다.
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_id")
private Long id;
@Column(nullable = false)
private String userId;
@Column(nullable = false)
private String password;
@Column(nullable = false)
private String email;
@Column(nullable = false)
private String nickname;
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private JobEnum job;
@OneToOne(mappedBy = "member", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JsonManagedReference
private Profile profile;
@OneToMany(mappedBy = "member", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<JoinChatRoom> joinChatRooms = new ArrayList<>();
@Builder
public Member(String userId, String password, String email, String nickname, JobEnum job) {
this.userId = userId;
this.password = password;
this.email = email;
this.nickname = nickname;
this.job = job;
}
public void addChatRoom(JoinChatRoom joinChatRoom) {
joinChatRooms.add(joinChatRoom);
}
}
PostMan으로 확인하면 채팅방이 정상정으로 생성되고 추가된다.
728x90
'TIL' 카테고리의 다른 글
[TIL - 20230429] WebSocket + Stomp 적용기2 (0) | 2023.04.29 |
---|---|
[TIL - 20230428] WebSocket + Stomp 적용기1 (0) | 2023.04.29 |
[TIL - 20230427] message properties 사용한 @Valid 메시지 처리 (0) | 2023.04.27 |
[TIL - 20230426] Enum 타입 필드 검증을 위한 커스텀 애노테이션 생성 (0) | 2023.04.26 |
[TIL - 20230420] ControllerAdvice, ExceptionHandler 전역 예외 처리 (0) | 2023.04.20 |