Hibernate
JPA 인터페이스의 구현체다.
데이터 모델과 객체 모델 불일치 문제
https://en.wikipedia.org/wiki/Object%E2%80%93relational_impedance_mismatch
객체 지향 프로그래밍과 관계형 데이터베이스 간의 구조적인 불일치 구체적인 사례는 위키에 잘 나와있다.
EntityManager와 EntityManagerFactory
엔티티 매니저의 생성 과정은 다음과 같다.
persistence.xml의 설정 정보를 사용해 EntityManagerFactory 생성한다.
src/main/resources 폴더 아래에 META-INF 폴더를 만들고 persistence.xml 파일을 만들어 보자
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
<persistence-unit name="demo">
<class>com.example.demo.models.Person</class>
<properties>
<property name="jakarta.persistence.jdbc.url"
value="jdbc:postgresql://localhost:5432/postgres"/>
<property name="jakarta.persistence.jdbc.user"
value="postgres"/>
<property name="jakarta.persistence.jdbc.password"
value="password"/>
</properties>
</persistence-unit>
</persistence>그리고 EntityManagerFactory를 생성하는 코드는 다음과 같다.
우선 Persistence 클래스를 살펴보자. 이 클래스의 주요한 역할은 EntityManagerFactory 개체를 생성하는 것이다.(bootstrap) createEntityManagerFactory라는 메서드를 통해서 EntityManagerFactory를 생성할 수 있다. createEntityManagerFactory의 메서드 시그니처는 다음과 같다.
매개변수로 String 타입의 persistenceUnitName을 받게 된다. persistence.xml의 에서 persistence unit의 이름을 지정할 수 있다.
@BeforeAll 어노테이션을 사용한 이유는 무엇일까? createEntityManagerFactory는 JPA를 동작시키기 위한 기반 개체를 생성하고, 커넥션 풀을 생성하는 등 비용이 큰 메서드다. 따라서 테스트에서 오직 한 번만 실행하기 위해서 @BeforeAll 키워드를 사용했다. @BeforeAll 어노테이션을 사용하기 위해서는 static 해야하기 때문에 멤버 변수와 테스트 멤버 함수 createEntityManagerFactory에 static 키워드가 붙는다.
일반적으로 EntityManagerFactory는 어플리케이션 전체에서 딱 한 번만 생성하고 공유해서 사용해야한다. 즉 싱글턴으로 만들어 global하게 접근하도록 한다.
"No persistence provider for EntityManager named demo", “Could not find any META-INF/persistence.xml file in the classpath” 에러
src/main/resources 폴더 아래에 META-INF 폴더를 만들고 persistence.xml 파일을 만들어 persistence config 데이터를 명시해야함
com.example.demo.models.Person
xml의 구문은 entity class를 persistence unit의 persistence context에 등록하는 것을 명시한다. 즉 persistence provider(JPA 구현체)에게 Person 클래스가 persistence unit이 관리하는 엔티티라는 것을 알려주게 된다.
따라서 Person 클래스에 @Entity 어노테이션 표기가 필요하다.
Unable to locate entity descriptor
mapping 정보가 없으면 에러가 발생함
객체에 @Entity 어노테이션을 추가하면 해결할 수 있음
참고로 entity descriptor는 entity class와 data base의 테이블의 mapping정보를 가진 metadata라고 생각하면 된다.
EntityDescriptor에서 descriptor의 의미
코딩할 때 자주 볼 수 있는게 Descriptor라는 단어다. 일반적인 descriptor의 의미를 알아보자.
descriptor라는 용어는 보통 프로그래밍에서 다른 데이터 구조나 개체에 대한 정보를 제공하는 데이터 구조 또는 개체다. 즉 본질적으로 descriptor는 메타데이터를 가지고 있는 컨테이너다. 어떤 자원, entity, 파일 등에 대해서 이들을 쉽게 관리할 수 있도록 메타데이터를 컨테이너화(추상화 + 캡슐화)했다고 생각하면 됨
대표적으로 예시를 확인해보자.
File Descriptors 운영체제에서 파일에 접근할 때 사용하는 abstract indicator
Class Descriptors OOP의 reflection 환경에서 class descriptor은 클래스에 대한 메타데이터를 가지고 있는 데이터 구조다.
DB Schema Descriptor 말 그대로 데이터베이스 스키마(table, column, data type, relationship, constraint) 즉 메타데이터를 가지고 있는 데이터 구조다. ORM 프레임워크들이 이를 통해 데이터베이스와 상호작용하게 된다.
Entity에서 default 생성자
기본 생성자가 없으면 컴파일 에러가 발생한다.
https://www.baeldung.com/jpa-no-argument-constructor-entity-class
컬렉션으로 조회하기 : JPQL과 entityManager의 createQuery
JPQL을 이용할 때 2가지 메서드 중 선택해서 사용할 수 있다.
이 중 TypedQuery를 반환하는 메서드를 사용하는 것을 추천한다. 제너릭으로 entity를 컬렉션으로 다루기 쉽게 구현했기 때문이다.
TypedQuery에서 결과를 조회하는 방법은 다음과 같다.
X 타입에 대한 리스트를 반환한다
Last updated