개발/JPA

[JPA 기본] 2. JPA 소개

Dahee Joy Cha 2021. 12. 3. 00:05

1. SQL 중심적인 개발의 문제점

1.1 반복되는 CRUD 쿼리 작성 작업

INSERT, SELECT, UPDATE, DELETE....계속 반복만하는 지루한 작업의 연속이다. 

 

1.2 필드 추가시 객체 변환, 관련 쿼리 일괄 변경 

(이건 실제 내 경험)최근 프로젝트에서 실제로 일어난 일이다. 

기존의 정책에서는 회원 정보 테이블에서 NAME이라는 컬럼을 사용하고 있었다. 이 안에 사용자 성, 이름 모두 포함되었다.

그런데, "우리는 글로벌 서비스니까, 외국인들도 사용하기 쉽게 성, 이름을 구분해서 입력 받아야겠다!"라는 요구사항이 들어왔다. 

FIRST_NAME, LAST_NAME으로 필드 추가는 쉬웠지만, NAME 컬럼을 사용하는 쿼리를 조회한 결과 수백개의 쿼리가 나왔다 (흑흑)

결국 몇 일에 걸쳐 FIRST_NAME 과 LAST_NAME을 추가하는 노가다를 수행해야만 했다. (ㅂㄷㅂㄷ)

"성, 이름 추가해주세요"라고 해맑게 웃는 기획자에게 차마 나쁜 말은 못하고.. JPA를 사용했더라면 금방 끝날 작업이었을 것이다. 

 

1.3 패러다임의 불일치 : 관계형 VS 객체지향형

관계형 접근의 불편함

- 개발자는 객체를 관계형 DB에 저장하기 위해 매번 쿼리를 작성해야한다. 

- 상속 관계의 객체를 만들기 위해 JOIN을 해줘야한다. 

예) 

즉. COMIC BOOK을 가져오기 위해, 아래 코드처럼 매번 조인해야한다. 

SELECT NAME, PRICE, GENRE
FROM BOOK a
INNER JOIN  COMIC BOOK b
ON a.ID = b.ID

 

깔끔하게 자바 컬렉션에서 조회하자

ComicBook book1 = list.get(comicBookId)

 

 

2. JPA 소개 

2.1 애노테이션

  • @Entity: JPA가 관리할 대상으로 지정함. 
  • @Id: PK로 지정
  • @Table(name="EXAMPLE"): 테이블의 명을 별도로 지정할 경우
  • @Column(name="username"): 컬럼명 별도 지정

2.2 JPA 사용시 주의 사항

  • 주의사항 1. 엔티티 매니저 팩토리는 하나만 생성하여 애플리케이션 전체에서 공유한다.
  • 주의사항 2. 하나의 작업 (예. 고객이 가입)을 할 때마다 EntityManager를 새로 만들것
    • EntityManager는 각 변경 사항의 상태값을 지닌다. 따라서 엔티티 매니저는 쓰레드간 공유해서는 안된다. 
  • 주의사항 3. 모든 DB 로직은 transaction 내부에서 실행되어야 한다.
EntityTransaction tx = em.getTransaction();
tx.begin();
// DB 로직
tx.commit
  • 주의사항 4. UPDATE 쿼리 동작 방식을 꼭 기억하자. 
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
    Member findMember = em.find(Member.class, 2L);
    findMember.setName("helloJPA");

    tx.commit();
} 

** setName 이후 em.persist(member)를 해줄 필요가 없다. 

왜냐면, findMember는 JPA에서 관리하는 대상이되고, 트랜젝션을 커밋하기전 객체에 변환이 있을 경우, JPA가 알아서 update 쿼리를 날리기 때문이다. 

 

2.3 persistence.xml 의 주요 설정값

2.3.1 EntityFactoryManager의 이름 지정

<persistence-unit name="hello">

 

2.3.2 JPA 추가/수정 로직 실행시, 쿼리 내용을 로그로 보여줌, 

<property name="hibernate.show_sql" value="true"/>

 

 

2.3.3 쿼리 로그를 보기 좋게 포맷팅

<property name="hibernate.format_sql" value="true"/>

 

2.3.4 실행된 쿼리의 내용을 코멘트로 알려줌. 

<property name="hibernate.use_sql_comments" value="true"/>

 

# 코멘트 예시
예) /* insert hellojpa.Member */

 

2.4 JPQL(Java Persistence Query Language)이란?

JPA에서 제공하는 메서드만으로는 복잡한 쿼리 작성이 어렵다.

(예. 키가 150cm이상인 학생을 출력하는 조건문)

-> 조건 검색에 적합하도록 JPQL 탄생 

 

정리

1. JPA의 모든 변경은 트랜젝션 안에서 일어나야만 한다. 

2. 트랜젝션은 commit을 해주자. 

EntityTransaction tx = em.getTransaction();
tx.begin();
// CRUD 로직
tx.commit();

3. 자원을 다 사용하면 entityManager는 닫아주자. (데이터 베이스 커넥션 반환 위해서)

EntityManager em = emf.createEntityManager();
// JPA 로직
 em.close();

4. WAS 내려갈 때 entityManagerFactory도 닫아주자. 

Connection pooling 등 내부 리소스 반환해야하니까!

EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
// JPA 로직
emf.close();