본문 바로가기

개발/JPA

[JPA 기본] 2. JPA 소개

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();