Hibernate Proxy객체가 실제객체로 변환이 안돼요
46
작성한 질문수 2
먼저 Entity Code부터 보여드리겠습니다.
FieldGroupMapping(부모)
@Entity
@Table(name = "FIELD_GROUP_MAPPING")
@Getter
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class FieldGroupMapping extends CreationAuditingEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "FIELD_GRP_MPPG_ID", nullable = false)
private Long id;
@Column(name = "FIELD_CD", length = 50, nullable = false)
private String fieldCd;
@ManyToOne(fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "FIELD_CD",
referencedColumnName = "FIELD_CD",
insertable = false,
updatable = false,
foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private FieldMetadata field;
}
FieldMetadata (자식)
@Entity
@Table(name = "FIELD_METADATA")
@Getter
@SuperBuilder
@AllArgsConstructor
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "FIELD_TYPE")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class FieldMetadata extends CreationAuditingEntity {
@Id
@Column(name = "FIELD_CD", length = 50, nullable = false)
private String fieldCd;
@Column(name = "LABEL", length = 50, nullable = false)
private String label;
@Enumerated(EnumType.STRING)
@Column(name = "DATA_TYPE", columnDefinition = "varchar(20)", nullable = false)
private FieldDataType dataType;
}
RealFieldMetadata (상속된 자식)
@Entity
@Table(name = "REAL_FIELD_METADATA")
@Getter
@SuperBuilder
@AllArgsConstructor
@DiscriminatorValue(FieldDiscriminatorValues.D_REAL)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@PrimaryKeyJoinColumn(name = "FIELD_CD")
public class RealFieldMetadata extends FieldMetadata {
@Enumerated(EnumType.STRING)
@Column(name = "TABLE_ALIAS", columnDefinition = "varchar(50)", nullable = false)
private TableAlias tableAlias;
@Column(name = "COLUMN_NAME", nullable = false, length = 50)
private String columnName;
@Builder.Default
@Convert(converter = BooleanYNConverter.class)
@Column(name = "REQUIRES_JOIN", nullable = false, columnDefinition = "char(1) default 'N'")
private boolean requiresJoin = false;
@Enumerated(EnumType.STRING)
@Column(name = "JOIN_TABLE", columnDefinition = "varchar(50)")
private TableAlias joinTable;
}
FieldGroupMapping 과 FieldMetadata는 1:N 관계입니다.
List<String> idList = List.of("GD01", "GD02", "GD03");
// fetch join 없이 조회
List<FieldGroupMapping> fieldGroupMappings1 = fieldGroupRepository.findAllById(idList);
Long gridId = 1L;
// fetch join으로 조회
List<FieldGroupMapping> fieldGroupMappings2 = gridRepository.getGrid(gridId)
.map(Grid::getFieldGroupMapping)
.toList();
for (FieldGroupMapping mapping1 : fieldGroupMappings1) {
FieldMetadata field = mapping1.getField();
// 여기서 BreakPoint로 field를 보면 Proxy 객체
}
for (FieldGroupMapping mapping2 : fieldGroupMappings2) {
FieldMetadata field = mapping2.getField()
// 여기서 BreakPoint로 field를 보면 실제 객체 (Unproxy상태)
}
위 상황에서 첫번째 fieldGroupMappings1을 조회할땐 fetch join없이 hibernate로만 조회합니다.
두번째 fieldGroupMappings2를 조회할땐 Grid -> FieldGroupMapping -> field 연관관계 모두 fetch join을 써서 조회합니다.
제 지식으로는 두개 for문에서 모두 field는 Unproxy상태여야합니다.
단, fetch join이 없는 첫번째 리스트에서는 Select Query가 나가겠죠.
하지만, 테스트 결과는 첫번째 리스트에서의 field는 계속 Proxy상태로 되어있어. field 내부의 필드들이 null로 되어있었습니다.
또, 제 어플리케이션의 설정으로 default batch size는 1000으로 되어있어. select문의 조건에 in절로 채워져서 쿼리가 1번 발생하였습니다.
제 지식으로는 Select쿼리가 발생하였으므로, 첫번째 리스트도 field는 실제 객체여야하는데 왜 프록시객체로 남아있을까요? FieldMetadata 엔티티가 상속Entity여서 발생하는 문제일까요?
정답을 알려주세요 ㅠㅠㅠ
답변 1
0
안녕하세요, 인프런 AI 인턴입니다.
papakang22님, 설명하신 문제를 바탕으로 Hibernate에서 발생할 수 있는 프록시 관련 이슈를 살펴보겠습니다.
첫 번째로, fetch join이 없는 경우에는 Hibernate가 연관된 객체를 필요 시점(즉, 실제 데이터 접근 시점)에 lazy loading을 통해 로딩합니다. 이때, FieldMetadata가 @ManyToOne 관계이므로 기본적으로 LAZY 로딩 전략을 사용합니다. 따라서 mapping1.getField() 호출 시 FieldMetadata의 실제 객체가 아닌 프록시 객체로 반환될 수 있습니다.
반면, 두 번째 케이스에서는 fetch join을 사용하여 쿼리 단계에서 필요한 데이터를 모두 가져오기 때문에 결과적으로 프록시 객체가 아닌 실제 객체로 로드됩니다.
두 경우 간의 차이는 @ManyToOne(fetch = FetchType.EAGER) 설정에 기인할 수 있습니다. EAGER 로딩 설정에도 불구하고 정상적으로 로딩되지 않는 경우가 발생할 수 있으므로, 다음을 확인해 보시는 것이 좋습니다:
EntityManager Configuration:
FetchType.EAGER로 설정했음에도 프록시 객체로 반환되는데는 여러 설정 및 환경적 요인이 있을 수 있으니, EntityManager 설정 및 환경을 확인해 보세요.Inheritance 전략: 상속 구조(
@Inheritance(strategy = InheritanceType.JOINED))로 인해 문제 발생 가능성이 있을 수 있습니다. 이런 상황에서는 해당 객체의 타입 캐스팅 및 초기화 과정에서 문제가 발생할 수 있으므로 상속 구조 내의 설정을 확인해 보세요.Hibernate Initialization 호출: 명시적으로 초기화할 수 있도록
Hibernate.initialize(object)를 통해 프록시 객체를 초기화하는 것도 한 가지 방법입니다.Hibernate 버그 확인: 사용중인 Hibernate 버전에서 관련된 알려진 버그가 없는지 공식 문서를 통해 확인이 필요합니다.
아래의 Spring Data JPA 공식 문서도 도움이 될 수 있으니 참고 바랍니다:
위 방법으로 해결되지 않는다면, 환경 설정 상태를 좀 더 세부적으로 점검하시거나, 소규모 프로젝트로 테스트해보는 것도 좋은 방법일 수 있습니다. 추가적인 문제가 있으면 다시 질문 주시면 감사하겠습니다.
로그인 확인
0
20
2
서비스에서와 컨트롤러의 @Vaild 적용 차이에 대해서
0
54
2
해결했습니다
0
40
1
지금 강의가 어려우신분 추천드립니다.
0
60
1
기존의 완성된 CRUD의 Build.gradle에 security관련 dependency를 추가하면 문제가 생깁니다.
0
66
2
EmailSender 관련 문의
0
57
1
CRA ? 질문입니다
0
54
1
[해결됨]마지막 강의 내용 수정 화면이 기능을 못하네요.
0
54
1
[해결됨]부분적으로 화면 이동이 안되는 부분이 있습니다.
0
85
6
aws 계정 생성 질문
1
78
1
조회 메서드 네이밍 질문
0
70
1
음성불량
0
53
1
장애 격리 관련해서 궁금한 부분이 있어요
0
65
2
질문있습니다.
0
53
1
코드 깃허브는 없을까요?
1
70
2
핵사고날 아키텍처 기반으로 멀티 모듈 설계 시 질문드립니다..
0
78
2
인넬리제이 무료버전
0
73
2
Post, PostEntity에서 User, UserEntity 의존
0
66
1
내부 객체 직접 접근에 관하여.
0
110
2
CertificationServiceTest
0
61
1
FlushModeType.COMMIT (12:45) 예시코드 질문
0
71
1
readme에 대한 자료는 따로 받아볼수 있나요?
0
106
2
InvalidCurriculumException DIP 적용 여부 문의
0
83
2
Inner class로 Config를 지정하는 이유
0
66
2





