JPA 구동방식

Moon·2022년 8월 5일
0
post-thumbnail

💡 JPA 구동방식

1) EntityManagerFactory 생성

JPA를 시작하기 위해서는 persistence.xml에 설정정보를 사용해서 엔티티 매니저 팩토리를 생성해야 한다.

EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

이렇게 작성해주면 META-INF/persistence.xml파일에서 이름이 hello인 영속성 유닛을 찾아 엔티티 매니저 팩토리를 생성한다. 설정 정보를 읽어서 JPA를 동작시키기 위해서는 객체를 만들고 경우에 따라 데이터 커넥션 풀을 하기 때문에 EntityManagerFactory는 만드는데 드는 비용이 상당히 크다. 그래서 애플리케이션 내에서 매번 생성하는 것이 아니라 딱 한 번만 생성해서 공유해서 사용해야 한다.

2) 엔티티 매니저 생성

EntityManager em = emf.createEntityManager();

EntityManagerFactory에서 EntityManager를 생성한다. 객체를 대신 저장해주는 Java의 컬렉션같은 존재라고 생각하면 된다. 엔티티를 관리하는 역할을 하는데 내부에서 데이터 커넥션을 유지하면서 데이터베이스와 통신한다. DB커넥션과의 밀접한 관계로 인해 여러 스레드가 접근하면 동시성 문제가 발생하기 때문에 스레드끼리 공유하거나 재사용하면 안 된다.

3) 종료

사용이 끝난 엔티티 매니저는 반드시 종료해야 한다. 애플리케이션 종료시에는 엔티티 매니저 팩토리도 종료해야 한다.

em.close();

emf.close();

트랜잭션 관리

JPA를 통해서 가져온 Entity는 JPA가 관리한다. 트랜잭션을 커밋하는 시점에 다 체크하고 쿼리를 날린다. 비즈니스 로직이 정상적으로 동작하는 경우에는 커밋하고 예외가 발생하면 트랜잭션을 롤백한다.

EntityTransaction tx = em.getTransaction();

try {
	tx.begin();	//트랜잭션 시작
    logic(em);	// 비즈니스 로직 실행 
    tx.commit();	// 트랜잭션 커밋

} catch (Exception e) {
	tx.rollback();	// 예외 발생시 트랜잭션 롤백
}

가장 중요한 점은 JPA의 모든 데이터 변경은 트랜잭션 안에서 실행되야 한다는 것이다.
RDB는 데이터 변경을 트랜잭션 안에서 하도록 설계되어 있다. DB는 내부적으로 다 트랜잭션 개념을 가지고 있기 때문에 트랜잭션을 걸지 않아도 처리해준다.

비즈니스 로직

등록, 수정, 삭제, 조회 작업은 엔티티 매니저를 통해 수행된다.

// 등록
em.persist(member);

// 수정
member.setAge(20);

단순히 엔티티 값만 변경하면 JPA가 어떤 엔티티가 변경되었는지 커밋 시점에 체크해서 UPDATE 쿼리를 생성해 데이터베이스의 값을 변경한다.

// 조회 
Member findMember = em.find(Member.class, id);

// 삭제 
em.remove(member);

- find() : 한 건 조회

  • 엔티티 타입과 값(@Id로 테이블의 기본 키와 매핑한 식별자 값)으로 엔티티 하나를 조회하는 가장 단순한 조회 방법

✔️ JPQL (Java Persistence Query Language)

✏️ 나이가 18살 이상인 회원을 모두 검색하고 싶다면? 위에서 설명한 find()메서드로 모두 조회할 수 있을까?

JPA를 사용하면 엔티티 객체를 중심으로 개발하고 DB에 대한 처리는 JPA에게 맡겨야 한다. 대상이 테이블이 아니라 객체이기 때문에 검색하려면 모든 데이터를 애플리케이션으로 불러와 엔티티 객체로 변경해줘야 한다. 테이블이 한 두개일 때는 상관 없지만 테이블이 수십 ~ 수백 개 되는 경우는 사실상 불가능하다.

👉 내가 원하는 데이터를 데이터베이스에서 불러오기 위해 JPA에서는 JPQL이라는 쿼리 언어를 사용한다.

List<Member> result = em.createQuery("select m from Member as m", Member.class)
	.getResultList();
   

대상이 테이블이 아니라 객체! 위의 "select m from Member~"에서 Member는 MEMBER 테이블이 아니라 회원 엔티티 객체를 의미한다. JPQL은 테이블을 알지 못하기 떄문에 쿼리 생성 메소드를 먼저 실행해 쿼리 객체를 생성한 후 그 객체의 getResultList() 메소드를 호출한다.


💻 참고 )

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 김영한님 강의
자바 ORM 표준 JPA 프로그래밍 (김영한)

profile
매일 성장하는 개발자 되기😊

0개의 댓글