| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- 자바스크립트
- 스프링
- 서버
- 쿼리
- JavaScript
- java
- 정리
- BACK-END
- 스프링부트
- spring
- 코드테스트
- 미니정리
- jpa
- 알고리즘
- 디자인 패턴
- 프로그래머스
- 자바
- SQL
- 백엔드
- node.js
- oracle
- 데이터베이스
- web
- 프런트엔드
- 코드 테스트
- jsp
- Next.js
- 프론트엔드
- 오라클
- MySQL
- Today
- Total
참치코더의 꿈 메모장
JPA / @MappedSuperclass, 프록시 개념 정리 본문

@MappedSuperclass
- 추상 클래스랑 비슷한데, @Entity는 실제 테이블과 매핑되지만 @MappedSuperclass는 실제 테이블과는 매핑되지 않는다.
- 단순히 매핑 정보를 상속할 목적으로만 사용된다.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
// @MappedSuperclass로 추상 클래스를 생성
@MappedSuperclass
public abstarct class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
}
// 1. 전혀 상관없는 Member 클래스
// 부모에게 상속받은 id 속성의 컬럼명을 MEMBER_ID로 재정의한다.
@Entity
// 1. 1개 속성만 변경할때 @AttributeOverride(name = "id", column = @Column(name = "MEMBER_ID"))
// 2. 2개 이상의 매핑 정보를 재정의 할때
@AttributeOverrides({
@AttributeOverride(name = "id", column = @Column(name = "MEMBER_ID")),
@AttributeOverride(name = "name", column = @Column(name = "MEMBER_NAME"))
})
public class Member extends BaseEntity {
// ID 상속
// NAME 상속
private String email;
}
// 2. 전혀 상관없는 Seller 클래스
@Entity
public class Seller extends BaseEntity {
// ID 상속
// NAME 상속
private String shopName;
}
|
cs |
- BaseEntity에는 객체들이 주로 사용하는 공통 매핑 정보를 정의한다.
- 자식 엔티티들은 상속을 BaseEntity의 매핑 정보를 물려받는다.
부모로 부터 받은 매핑 정보를 재정의 하려면
1. @AttributeOverrides나 @AttributeOverride 사용
연관관계를 재정의 하려면
2. @AssociationOverrides나 @AssociationOveride 사용
- 그러나 실무에서는 사용을 잘 하지 않는다. (애초에 이걸 사용하면 그냥 설계가 잘못된 것)
정리
1. @MappedSuperClass는 자식 클래스에 엔티티의 매핑 정보를 상속하기 위해 사용한다.
2. @MappedSuperClass로 지정한 클래스는 @Entity가 아니기 때문에 em.find나 JPQL에서 사용할 수 없다.
진정한 상속관계 매핑은 https://chamchicoder.tistory.com/278
JPA / 상속관계 매핑 (SINGLE_TABLE, JOINED, TABLE_PER_CLASS)
객체지향에서는 클래스 상속을 통해 공통 속성을 물려주지만, 관계형 데이터베이스는 상속 개념이 없다. 그래서 JPA는 상속 구조를 테이블 구조로 변환하기 위해 3가지 전략을 사용한다. 1. 단일
chamchicoder.tistory.com
프록시
- 프록시란 실제 엔티티 대신 사용되는 가짜 객체이다.
- JPA가 엔티티(데이터베이스)를 즉시 로딩하지 않고, 나중에 필요할 때(DB 접근이 필요할 때) 실제 데이터를
가져오기 위해 사용하는 객체이다.
언제 만들어질까?
- 프록시는 지연 로딩(Lazy Loading) 시점에 생성된다.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
@Entity
public class Member {
@Id
private Long id;
private String name;
@ManyToOne(fetch= FetchType.LAZY)
private Team team; // 지연 로딩 관계
}
// 사용
Member member = em.find(Member.class , 1L);
Team team = member.getTeam(); // 프록시 객체만 생성되고, 실제 엔티티 객체가 생성되지는 않는다.
-> 진짜 Team이 아니라, Team을 상속받은 프록시 클래스 생성
-> 내부에 실제 Team을 로드하는 로직이 들어 있음 -> 필요할 때만 DB 접근해서 진짜 엔티티를 초기화함 |
cs |
프록시의 동작 과정
1. 지연 로딩 시점
: member.getTeam() 호출 시, 프록시 객체가 반환된다 (DB 접근 X)
2. 초기화 시점
: 프록시의 메서드(team.getName() or Hibernate.initialize(team)) 호출 시 내부에서
영속성 컨텍스트에 실제 Entity를 만들어달라고 요청하고 해당 프록시가 실제 생성된
엔티티의 메소드를 상속받아서 해당 데이터를 실행시킨다.
3. 초기화 이후
: 이제 프록시는 실제 Team 엔티티처럼 동작한다. (데이터는 캐싱됨)
주요 메서드...
em.getReference(EntityClass, id) : 프록시 객체를 직접 얻음(DB 접근 안 함)
em.find(EntityClass, id) : 실제 엔티티를 조회한다 (DB 접근 함)
entityManagerFactory.getPersistenceUnitUtil().isLoaded(entity)
: 프록시가 초기화되었는지 확인(맞으면 true, 아니면 false)
Hibernate.initialize(entity) : 프록시 객체를 강제로 초기화
(Hibernate 전용, JPA는 공식으로 지원하는 메서드가 없다)
프록시 주의사항
1. Team team1 = em.find(Team.calss, 1L);
Team team2 = em.getReference(TEam.class, 1L);
System.out.println(team1 == team2) //false 가 뜰 수 있다.
-> 실제 엔티티랑 프록시 엔티티랑 동일성(==)비교가 실패할 수 있다.
-> 항상 식별자 기반(equals)으로 비교해야 한다!!
team1.getId().equals(team2.getId()); //true
2. Team team = member.getTeam(); // 프록시 반환
em.clear();
em.close(); // 영속성 컨텍스트 종료
team.getName(); // LazyInitializationException 발생
-> DB 접근이 필요한데, 영속성 컨텍스트가 초기화 되어 없으니 예외 발생
3. 프록시는 진짜 엔티티처럼 보이지만, 타입이 다르다
그래서 타입 비교나, 실제 엔티티와의 equals, hashcode, 직렬화 시 문제가 생긴다.
-> 해결책은 instanceof 사용, Entity로 바로 반환하지말고 DTO로 반환하기, fetch join을
사용해야 한다.
'JPA' 카테고리의 다른 글
| JPA / 기본값 타입, 임베디드 타입 정리, 불변객체란?, 그에 따른 비교 (0) | 2025.10.24 |
|---|---|
| JPA / 지연로딩(lazy loading), 즉시로딩(eager loading), 영속성 전이(cascading), 고아객체(Orphan) 정리 (0) | 2025.10.21 |
| JPA / 상속관계 매핑 (SINGLE_TABLE, JOINED, TABLE_PER_CLASS) (1) | 2025.10.13 |
| JPA / 일대일(OneToOne) 매핑, 다대다(ManyToMany) 매핑(코드 위주) (0) | 2025.10.10 |
| JPA / 일대다(oneToMany) 관계 매핑 정리 (0) | 2025.10.09 |