JPA
: Java의 ORM 기술 표준(인터페이스)
객체와 RDB 간의 매핑을 자동으로 처리 → 패러다임 불일치 문제 해결
persist(), find(), remove()` 같은 메서드로 간단하게 데이터를 조작할 수 있다.jpa.persist(tutor);
Tutor tutor = jpa.find(Tutor.class, tutorId);
tutor.setName("새로운 이름");
jpa.remove(tutor);
유지보수성 증가
객체 필드가 변경되어도 JPA가 자동으로 SQL을 생성하므로, 직접 SQL을 수정할 필요가 없음
패러다임 불일치 문제 해결
JPA는 @Inheritance 전략을 통해 테이블을 자동으로 매핑할 수 있다.
연관관계
JPA의 @ManyToOne, @OneToMany 등을 사용하여 객체 간 참조를 쉽게 설정
객체 그래프 탐색
fetch join을 사용하여 한 번의 SQL 실행으로 필요한 데이터를 모두 불러올 수 있다.
객체 비교
동일한 트랜잭션 내에서는 find()를 호출해도 같은 인스턴스를 반환하므로, == 비교 연산이 true
성능 최적화
-동일한 트랜잭션 내에서는 같은 객체를 재사용하여 성능을 최적화합니다.
-지연 로딩(Lazy Loading)
→ 필요한 시점에만 데이터를 조회, 불필요한 SQL 실행을 방지!!
⭐️Hibernate
데이터베이스와 Hibernate가 상호작용할 때 특정 데이터베이스에 맞게 SQL 구문을 자동으로 조정 (어떤 DB언어를 사용하던지 알아서 번역해줌)
: JPA에서 엔티티 객체를 관리하는 1차 캐시(메모리 영역)
➡️ EntityManager가 엔티티를 CRUD할때 이를 관리해준다
➡️ 트랜잭션 범위 내에서 엔티티의 상태를 추적하고, 필요하면 DB와 동기화까지!
✅ 엔티티의 생명주기(상태) 4가지
| 상태 | 설명 |
|---|---|
| 비영속 | JPA가 관리하지 않는 객체 |
| 영속 | 영속성 컨텍스트에서 관리되는 객체 |
| 준영속 | 관리가 해제된 객체 |
| 삭제 | 삭제될 객체 → DB에서도 삭제 |
🔗 동일성 보장
: 같은 EntityManager에서 같은 엔티티를 여러번 조회하면 동일한 객체를 반환한다!
→ 1차 캐시 덕분
@Entity
class Member {
@Id @GeneratedValue
private Long id;
private String name;
}
//2번 선언해도 동일성 보장 덕분에 같은 객체를 반환하게 됨
Member member1 = em.find(Member.class, 1L);
Member member2 = em.find(Member.class, 1L);
System.out.println(member1 == member2); // true (같은 인스턴스)
두번 조회해도 DB에서 다시 가져오는게 아니고, 1차 캐시에서 반환되는 것
: JPA는 트랜잭션이 커밋될 때까지 Insert Update를 모아서 한 번에 처리함
em.persist(new Member("Alice"));
em.persist(new Member("Bob"));
System.out.println("SQL 실행 전"); // 여기까지 SQL 실행 X
em.flush(); // 강제 실행
System.out.println("SQL 실행 후"); // 여기서 SQL 실행됨
➡️ persist()를 호출해도 바로 SQL 실행❌, "영속성 컨텍스트"에 저장
➡️ flush() or 트랜잭션이 커밋될 때 한꺼번에 DB에 반영
: 엔티티가 영속상태면, JPA는 자동으로 변경을 감지해 Update 실행함
→ 즉 em.update() 같은 명령 호출하지 않아도 알아서 처리함
Member member = em.find(Member.class, 1L); // 1차 캐시에서 조회
member.setName("Charlie"); // setter로 값 변경
// 트랜잭션 커밋 시점에 자동으로 UPDATE 실행
em.getTransaction().commit();
트랜잭션 커밋 시점에 자동으로 UPDATE SQL 실행
=> 따로 update() 호출 안해도 JPA가 알아서 반영해주는것!!
: 1차 캐시는 유지하면서 영속성 컨텍스트의 변경 내용을 DB와 동기화하는 과정
💡 flush()가 발생하는 시점
1. 트랜잭션 커밋할 때 (commit())
2. JPQL 실행 직전 (Query 실행 전)
3. em.flush() 호출했을 떄
Member member = new Member("David");
em.persist(member); // SQL 실행 X
em.flush(); // 강제 실행 (SQL 즉시 실행)
.clear() 호출하지 않으면 영속 상태는 유지된다!
| 키워드 | 하는 일 |
|---|---|
| 영속성 컨텍스트 | JPA가 엔티티를 관리하는 메모리 공간 (=1차 캐시) |
| 엔티티 상태 | 영속, 비영속, 준영속, 삭제 |
| 동일성 보장 | 같은 EntityManager에서 같은 엔티티 부르면, 재사용함(동일한 인스턴스 가져옴) |
| 쓰기 지연 | persist() 했다고 바로 INSERT하는게 아니라, 트랜잭션 시 한번에 실행함 |
| 변경 감지 | 세터로 값을 변경하면, JPA가 자동으로 업뎃해줌 |
| flush() | 영속성 컨텍스트의 바뀐 내용을 DB에 즉시 반영해줌 |
⭐️ 영속성 컨텍스트를 통해
성능 최적화, 동일성 보장, 자동 변경 감지 등의 핵편한 기능 제공
쓰기 지연 & 변경 감지 ➡️ 불필요한 SQL↓ & 성능↑