작성
·
459
1
강의를 들으면서 혼자 프로젝트를 진행중에 질문드립니다.
Member 와 Post 가 1:N 양방향 관계에 있고 지연로딩으로 설정하였습니다. 아래는 postService 클래스의 post를 저장하는 메소드 입니다.
public class PostService {
private final PostRepository postRepository;
@Transactional
public Long createPost(Post post){
log.info("new post = "+post);
postRepository.save(post);
Post byId = postRepository.findById(post.getId()).get();
log.info("Member = " + byId.getMember());
log.info("MemberPosts = " + byId.getMember().getPosts());
return post.getId();
}
일단 post가 제대로 저장이 됩니다. 근데 위 코드의 log.info("memberPosts = " + byId.getMember.getPost()) 에서 failed to lazily initialize a collection of role 에러가 발생합니다. 해당 오류가 영속성 컨텍스트가 종료되어 지연로딩이 불가능 해서 나온 오류라고 하셨는데, createPost 메서드에 @Transactional 에노테이션을 붙혀놨는데도 영속성 컨텍스트가 종료되나요?
오류가 나는 로그 위의 byId.getMember() 의 로그는 정상출력이 되는데 여기서 member는 영속성 컨텍스트가 살아있어서 getMember.getPost()와는 다른 결과가 나온 것인가요?
해당 코드를 실행했을 때 로그입니다.
2022-05-30 23:32:58.015 INFO 35864 --- [nio-8080-exec-1] com.mytube.service.PostService : new post = Post(title=dwq, member=Member(id=1, userId=a, password=a, userEmail=a))
2022-05-30 23:32:58.016 DEBUG 35864 --- [nio-8080-exec-1] org.hibernate.SQL :
call next value for hibernate_sequence
2022-05-30 23:32:58.017 INFO 35864 --- [nio-8080-exec-1] com.mytube.service.PostService : Member = Member(id=1, userId=a, password=a, userEmail=a)
2022-05-30 23:32:58.017 INFO 35864 --- [nio-8080-exec-1] c.mytube.web.interceptor.LogInterceptor : RESPONSE [e95af4ef-3220-4391-bbae-7e6fb049c9d0][/posts/new]
2022-05-30 23:32:58.018 ERROR 35864 --- [nio-8080-exec-1] c.mytube.web.interceptor.LogInterceptor : afterCompletion error!!
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mytube.domain.Member.posts, could not initialize proxy - no Session
그리고 문제가 되는 getMember.getPosts() 로그를 주석처리했을 때 로그입니다.
2022-05-30 23:35:19.862 INFO 39788 --- [nio-8080-exec-8] com.mytube.service.PostService : new post = Post(title=asd, member=Member(id=1, userId=a, password=a, userEmail=a))
2022-05-30 23:35:19.869 DEBUG 39788 --- [nio-8080-exec-8] org.hibernate.SQL :
call next value for hibernate_sequence
2022-05-30 23:35:19.873 INFO 39788 --- [nio-8080-exec-8] com.mytube.service.PostService : Member = Member(id=1, userId=a, password=a, userEmail=a)
2022-05-30 23:35:19.876 DEBUG 39788 --- [nio-8080-exec-8] org.hibernate.SQL :
insert
into
posts
(created_date, last_modified_date, created_by, last_modified_by, content, member_id, title, post_id)
values
(?, ?, ?, ?, ?, ?, ?, ?)
로그를 보니 post가 영속상태에 있어서 따로 select 쿼리가 나가지 않아도
Post byId = postRepository.findById(post.getId()).get();
의 결과를 영속성 컨텍스트에서 가져오고 post의 member 또한 post가 영속상태에서 프록시 member가 아닌 실제 member를 가진것같습니다.
근데 member.getPost()는 왜 영속상태가 끝났다는 걸까요??
답변 3
1
안녕하세요. 조진수님
엔티티를 세션에 보관하면 안됩니다. 세션에는 DTO를 보관해주세요.
지금 세션에 member 엔티티를 보관하고, 또 해당 엔티티를 엮어서 그대로 Post와 함께 persist하기 때문에 post를 다시 조회할 때 세션에 보관된 member가 조회되는 현상이 발생합니다. 이 member는 프록시 기능을 상실한 상태이기 때문에 이런 문제가 발생합니다.
감사합니다.
0
https://drive.google.com/file/d/17ZWGBPZ-WEz-XitsVn6qRvDIiisRuApS/view?usp=sharing
h2 데이터베이스를 키고 스프링부트 어플리케이션을 실행하고 localhost:8080 에서 로그인 후 글 게시판에 새글 작성을 하면 해당 오류가 나옵니다. 감사합니다
0
안녕하세요. 조진수님
전체 프로젝트를 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.
구글 드라이브 업로드 방법은 다음을 참고해주세요.
주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요
추가로 다음 내용도 코멘트 부탁드립니다.
1. 실행 방법을 알려주세요.
2. 어떻게 문제를 확인할 수 있는지 자세한 설명을 남겨주세요.
감사합니다.