👉에러 상황
먼저 에러는 Post 목록 조회할 때 발생했습니다. Post와 Like는 1:N 양방향 연간관계를 맺고 있습니다.
- Post 엔티티 구성
package com.duktown.domain.post.entity;
import com.duktown.domain.BaseTimeEntity;
import com.duktown.domain.comment.entity.Comment;
import com.duktown.domain.like.entity.Like;
import com.duktown.domain.user.entity.User;
import com.duktown.global.type.Category;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
import static javax.persistence.EnumType.STRING;
import static javax.persistence.FetchType.LAZY;
import static javax.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PRIVATE;
import static lombok.AccessLevel.PROTECTED;
@Entity
@Getter
@Builder
@AllArgsConstructor(access = PRIVATE)
@NoArgsConstructor(access = PROTECTED)
public class Post extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "post_id")
private Long id;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;
@Enumerated(STRING)
@Column(nullable = false)
private Category category;
@Column(length = 20, nullable = false)
private String title;
@Column(nullable = false, columnDefinition = "longtext")
private String content;
@Builder.Default
@OneToMany(fetch = LAZY, mappedBy = "post")
private List<Comment> comments = new ArrayList<>();
@OneToMany(fetch = LAZY, mappedBy = "post")
private List<Like> likes;
public void update(String title, String content){
this.title =title;
this.content =content;
}
}
- Like 엔티티 구성
package com.duktown.domain.like.entity;
import com.duktown.domain.BaseTimeEntity;
import com.duktown.domain.comment.entity.Comment;
import com.duktown.domain.post.entity.Post;
import com.duktown.domain.user.entity.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import static javax.persistence.FetchType.LAZY;
import static javax.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PRIVATE;
import static lombok.AccessLevel.PROTECTED;
@Entity
@Getter
@Builder
@AllArgsConstructor(access = PRIVATE)
@NoArgsConstructor(access = PROTECTED)
@Table(name = "likes")
public class Like extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "like_id")
private Long id;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "post_id")
private Post post;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "comment_id")
private Comment comment;
}
👉로그
Hibernate:
select
user0_.user_id as user_id1_18_,
user0_.created_at as created_2_18_,
user0_.modified_at as modified3_18_,
user0_.available_period as availabl4_18_,
user0_.deleted as deleted5_18_,
user0_.deleted_at as deleted_6_18_,
user0_.email as email7_18_,
user0_.login_id as login_id8_18_,
user0_.name as name9_18_,
user0_.password as passwor10_18_,
user0_.refresh_token as refresh11_18_,
user0_.role_type as role_ty12_18_
from
users user0_
where
user0_.deleted=0
and user0_.user_id=?
and user0_.login_id=?
Hibernate:
select
user0_.user_id as user_id1_18_,
user0_.created_at as created_2_18_,
user0_.modified_at as modified3_18_,
user0_.available_period as availabl4_18_,
user0_.deleted as deleted5_18_,
user0_.deleted_at as deleted_6_18_,
user0_.email as email7_18_,
user0_.login_id as login_id8_18_,
user0_.name as name9_18_,
user0_.password as passwor10_18_,
user0_.refresh_token as refresh11_18_,
user0_.role_type as role_ty12_18_
from
users user0_
where
user0_.deleted=0
and user0_.user_id=?
Hibernate:
select
like0_.like_id as like_id1_9_0_,
post1_.post_id as post_id1_11_1_,
like0_.created_at as created_2_9_0_,
like0_.modified_at as modified3_9_0_,
like0_.comment_id as comment_4_9_0_,
like0_.post_id as post_id5_9_0_,
like0_.user_id as user_id6_9_0_,
post1_.created_at as created_2_11_1_,
post1_.modified_at as modified3_11_1_,
post1_.category as category4_11_1_,
post1_.content as content5_11_1_,
post1_.title as title6_11_1_,
post1_.user_id as user_id7_11_1_
from
likes like0_
inner join
post post1_
on like0_.post_id=post1_.post_id
where
like0_.user_id=?
and (
like0_.post_id in (
? , ?
)
)
Hibernate:
select
count(*) as col_0_0_
from
comment comment0_
where
comment0_.post_id=?
and comment0_.deleted=0
👉해결
지연 로딩으로 생성된 프록시를 초기화(= 연관된 데이터를 가져오기)가 불가능한 상황임으로 원인은 Post 조회 결과가 반환 되면서 트랜잭션이 이미 종료된 이후에 Like 연관된 데이터에 접근하려 했기 때문이다.
방안1) 데이터를 가져올 떄 한번에 가져오는 즉시로딩으로 변경
@OneToMany(mappedBy = "post", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Like> likes = new ArrayList<>();
방안2) 트랜잭션 단위로 관리되도록 수정
조회 로직 내부에 캐싱 부분이 있어 해당 캐싱 부분에서 호출 부문을 @Transactional을 통해 같은 트랜잭션 내에서 관리되도록 작성.
'TIL > 트러블슈팅' 카테고리의 다른 글
[SpringBoot]비동기 Async는 프록시 기반 동작 (0) | 2025.01.30 |
---|---|
[Chocolatey] An existing Chocolatey installation was detected. (0) | 2025.01.22 |
[Node] getaddrinfo ENOTFOUND your-proxy-server (0) | 2024.02.28 |
[SpringBoot] No acceptable representation (1) | 2024.02.09 |
[Docker] Docker failed to initialize (0) | 2023.12.12 |