JPA가 무엇인지에 대해 오랫동안 이해하지 못하다가 이제서야 조금씩 이해가 가기 시작했습니다. 그동안 의문 가졌던것을 다 풀어볼까합니다. 아주 터무니없는 질문에 대한 답도 많을 예정이라 spring 고수분들에게는 추천드리지 않습니다.
- ORM ( Object-Relational Mapping )
JPA와 hibernate는 ORM 프레임워크로 잘 알려져 있습니다. 그런데 ORM이 무엇일까요?
ORM의 가장 큰 역할은 바로 객체 지향 프로그래밍과 관계형 데이터베이스 간의 패러다임의 차이를 해결해주는 역할을 합니다.
객체 지향 프로그래밍에서는 객체 간의 연관성을 중요시하며, 이를 객체 간의 참조로 나타냅니다. 하지만 관계형 데이터베이스에서는 테이블 간의 관계를 외래키로 표현합니다. 또한 객체 지향 프로그래밍에서는 객체의 상태를 중요시하며, 이를 객체의 필드로 표현합니다. 반면에 관계형 데이터베이스에서는 데이터의 무결성을 보장하기 위해 제약 조건을 설정하며, 이를 통해 데이터의 정합성을 유지합니다.
이러한 불일치 때문에 등장한 것이 바로 ORM이며 객체와 관계형 데이터베이스 간의 매핑을 자동화하여 불일치를 최소화합니다. - JPA와 hibernate 둘의 차이는 무엇일까?
- JPA
JPA는 Java Persistence API의 약자로, 자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스입니다. 여기서 중요하게 여겨야 할 부분은, JPA는 말 그대로 인터페이스라는 점입니다. JPA는 특정 기능을 하는 라이브러리가 아닙니다. - hibernate
Hibernate는 JPA라는 명세의 구현체입니다. JPA와 Hibernate는 마치 자바의 interface와 해당 interface를 구현한 class와 같은 관계입니다. JPA를 사용하기 위해서 반드시 Hibernate를 사용할 필요는 없습니다. - JPA 인터페이스를 보고 직접 내가 구현할순 없을까?
자신이 구현할수는 있으나 JPA 인터페이스의 모든 동작을 이해해야하므로 굉장히 어렵다고 합니다. 궁금해서 hibernate 소스코드를 찾아봤는데 뭔지 하나도 모르겠네요... https://github.com/hibernate/hibernate-orm
- JPA
- hibernate가 어떻게 동작하길래 구현하기 어려운걸까?
- JPA를 얘기할때 자주나오는 용어가 Persistent Context입니다. 1차 캐시라고 부르며 db로부터 엔티티를 관리, 캐싱합니다. EntityManager 또는 Session과 1:1 관계를 갖습니다. Session은 EntityManager의 구현체이며 db와 연결을 맺으며 생성됩니다.
- 신규 생성한 엔티티를 저장하면 persist()가 호출되고 AbstractEvent의 구현체인 PersistEvent를 넘겨 PERSIST 이벤트 그룹의 DefaultPersistEventListener의 onPersist가 호출되고 엔티티 영속화 작업이 동작합니다. 영속화란 엔티티가 PersistentContext 내에서 관리되는 ManagedEntity가 되는 것으로 이해하면 쉽습니다.
- 영속화된 엔티티는 EntityEntryContext에서 리스트로 관리됩니다. 신규 엔티티가 영속화 되기 위해 db에 insert해야하는데 바로 실행하지 않고 ActionQueue에 EntityInsertAction을 Enque하고 계속해서 Action들이 쌓입니다.
- 모든 영속화 작업이 끝나면 Session의 flush가 호출되고 FlushEvent를 Flush Event Group에 넘겨 DefaultFlushEventListener의 onFlush를 호출합니다. 그러면 ActionQeue의 executeActions를 실행하여 쌓인 Action들을 실행합니다.
- JPA를 얘기할때 자주나오는 용어가 Persistent Context입니다. 1차 캐시라고 부르며 db로부터 엔티티를 관리, 캐싱합니다. EntityManager 또는 Session과 1:1 관계를 갖습니다. Session은 EntityManager의 구현체이며 db와 연결을 맺으며 생성됩니다.
- 지연로딩, 즉시로딩은 뭐지?
- 지연로딩 - 엔티티를 실제 사용할 때 해당 엔티티와 관련된 객체를 가져오는 방식
불필요한 쿼리 실행을 최소화하고, 성능을 향상시킬 수 있습니다. 하지만, 사용자가 해당 필드를 사용할 때마다 DB에 쿼리를 실행하기 때문에, 일정한 오버헤드가 발생할 수 있습니다. - 즉시로딩 - 엔티티를 조회할 때, 해당 엔티티와 관련된 객체를 모두 가져오는 방식
지연 로딩보다 더 나은 성능을 보장할 수 있습니다. 하지만, 관련된 엔티티들을 모두 가져오기 때문에, 데이터 양이 많아질 경우 성능 문제가 발생할 수 있습니다.
- 지연로딩 - 엔티티를 실제 사용할 때 해당 엔티티와 관련된 객체를 가져오는 방식
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String content;
@OneToMany(mappedBy = "post") // 즉시로딩
private List<Comment> comments;
// 생성자, Getter/Setter, toString 등 생략
}
@Entity
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String author;
private String content;
@ManyToOne(fetch = FetchType.LAZY) // 지연 로딩
@JoinColumn(name = "post_id")
private Post post;
// 생성자, Getter/Setter, toString 등 생략
}
# Reference
chatgpt
https://suhwan.dev/2019/02/24/jpa-vs-hibernate-vs-spring-data-jpa/
https://brunch.co.kr/@anonymdevoo/47
'Back-end > Spring 기초개념' 카테고리의 다른 글
JPA 성능 최적화 (0) | 2024.04.28 |
---|---|
Entity에 setter를 사용하지 않는 진짜 이유 (1) | 2024.03.07 |
Instagram-clone 분석 (3) Controller (0) | 2023.05.05 |
Instagram-clone 분석 (3) DTO (0) | 2023.04.23 |
Instagram-clone 분석 (2) entity (3) | 2023.04.22 |