- 참조: 자바 ORM 표준 JPA 프로그래밍
- 이 글에 나오는 코드는 https://ocwokocw.tistory.com/118 글을 먼저 읽었다는 점을 전제로 작성한다.
- Java example
엔티티 매니저를 살펴보기 전에 우리가 DB를 다룰 때 일반적으로 사용하는 등록, 수정, 삭제, 조회 연산 예제 코드를 살펴보자. 아래 코드는 엔티티 매니저 설정, 트랜잭션 관리, 비즈니스 로직 3 부분으로 구성 되어있다.
@SpringBootApplication
public class JpaApplication {
public static void main(String[] args) {
SpringApplication.run(JpaApplication.class, args);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpatest");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
logic(em);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
private static void logic(EntityManager em) {
String id = "id1";
Member member = new Member();
member.setId(id);
member.setUserName("ocwokocw");
member.setAge(33);
em.persist(member);
member.setAge(20);
Member findMember = em.find(Member.class, id);
System.out.println("findMember: " + findMember);
List<Member> members = em.createQuery("select m from Member m", Member.class)
.getResultList();
System.out.println("member size: " + members.size());
em.remove(member);
}
}
위의 코드는 META-INF/persistence.xml 로 설정했을 때 EntityManagerFactory bean을 얻어오는 코드이다. 만약 application.properties 로 설정했다면 EntityManagerFactory 를 얻어올 때 아래처럼 Type 기반으로 ApplicationContext 에서 얻어와야 한다.
ApplicationContext appCtx = SpringApplication.run(JpaApplication.class, args);
EntityManagerFactory emf = appCtx.getBean(EntityManagerFactory.class);
위의 코드를 수행하면 아래와 같이 콘솔에 찍힌다. Mybatis 로 SQL 을 작성하지 않았는데도 SQL 문이 자동으로 출력되었다. 엔티티 매니저부터 천천히 살펴보도록 하자.
findMember: Member [id=id1, userName=ocwokocw, age=20]
Hibernate:
/* insert com.example.demo.member.Member
*/ insert
into
MEMBER
(age, NAME, ID)
values
(?, ?, ?)
Hibernate:
/* update
com.example.demo.member.Member */ update
MEMBER
set
age=?,
NAME=?
where
ID=?
Hibernate:
/* select
m
from
Member m */ select
member0_.ID as id1_0_,
member0_.age as age2_0_,
member0_.NAME as name3_0_
from
MEMBER member0_
member size: 1
Hibernate:
/* delete com.example.demo.member.Member */ delete
from
MEMBER
where
ID=?
- 엔티티 매니저
위의 예제코드에서 EntityManager 를 얻기까지의 동작과정은 아래와 같다.
- Persistence 가 META-INF/persistence.xml 설정 정보를 조회한다.
- 이 정보를 기반으로 EntityManagerFactory 를 생성한다.
- EntityManagerFactory 에서 EntityManager 를 생성한다.
EntityManagerFactory 는 JPA 구현체에 따라 DB 커넥션 풀 생성과 같은 작업을 하므로 비용이 아주 크다. 따라서 어플리케이션에서 한번만 생성한 후 공유해서 사용한다.
EntityManager 를 통해서 엔티티를 DB 에 CRUD 할 수 있으며 내부에 데이터소스를 유지하면서 DB와 통신한다. EntityManager 는 커넥션과 관련이 있으므로 스레드간 공유나 재사용을 하면 안된다.
사용이 끝난 EntityManager는 close로 종료해줘야 하고, 어플리케이션을 종료할 때에는 EntityManagerFactory를 종료한다.
- 트랜잭션과 비즈니스 로직
트랜잭션을 시작하려면 EntityManager 에서 트랜잭션 API 를 얻어와야 한다. main 코드를 보면 tx 에서 commit 과 rollback 을 함을 알 수 있다.
logic 메소드 안에서는 생성, 수정, 조회, 삭제를 하는데 동작을 간략하게 알아보면 아래와 같다.
- 생성: 엔티티를 저장하려면 EntityManager 의 persist() 메소드에 엔티티를 넘기면 된다.
- 수정: 수정이 조금 특이한데, setAge setter 로 변경만 했을 뿐 업데이트 동작으로 보이는 메소드를 호출하지 않았다. JPA 는 엔티티가 변경되는 과정을 추적하여 update 구문을 만들어서 수행한다.
- 삭제: remove() 메소드를 호출하여 해당 엔티티를 삭제한다.
- 단건 조회: @Id 로 지정한 필드로 find() 메소드로 단건을 조회한다.
- JPQL
위에서 CUD 와 단건조회는 엔티티 객체를 중심으로 개발하면 DB 처리는 JPA 가 해주었다. 하지만 검색 쿼리는 얘기가 다르다. 만약 엔티티 객체를 대상으로 검색하려면 DB 의 모든 데이터를 애플리케이션의 엔티티 객체로 변경해서 검색해야 한다.
JPA 는 필요한 데이터만 검색할 수 있게 JPQL 이라는 쿼리언어로 이 문제를 해결한다. SQL 과 문법이 거의 유사하긴 하지만 가장 큰 차이는 JPQL의 경우 엔티티 객체를 대상으로, SQL은 데이터베이스 테이블을 대상으로 쿼리한다고 할 수 있다.
JPQL을 사용한 문자열을 자세히 보면 "select m from Member m" 에서 Member 엔티티 객체이지 H2 의 MEMBER 테이블이 아니다.
'Framework and Tool > JPA' 카테고리의 다른 글
JPA - 영속성 관리 - 준영속과 병합 (0) | 2021.06.24 |
---|---|
JPA - 영속성 관리 - 플러시(flush) (0) | 2021.06.24 |
JPA - 영속성 관리 - 영속성 컨텍스트 (0) | 2021.06.24 |
JPA - 영속성 관리 - 엔티티의 생명주기 (0) | 2021.06.23 |
JPA - 환경구축 및 객체맵핑, persistence.xml (0) | 2021.06.23 |
댓글