본문 바로가기

공부 기록/Java

[JPA] 2장 - JPA 애플리케이션 개발

엔티티 매니저 설정

public class JpaMain {
    public static void main(String[] args) {

        // 엔티티 매니저 팩토리 생성
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("unit");

        // 엔티티 매니저 생성
        EntityManager em = emf.createEntityManager();

        ...
            
        // 엔티티 매니저 종료
        em.close();

        // 엔티티 매니저 팩토리 종료
        emf.close();

    }
}

엔티티 매니저 팩토리

- 생성 시 JPA를 동작시키기 위한 기반 객체를 만들고 JPA 구현체에 따라서는 데이터베이스 커넥션 풀도 생성하므로 생성 비용이 매우 크다. => 엔티티 매니저 팩토리는 애플리케이션 전체에서 딱 한 번만 생성하고 공유해서 사용해야 한다.

- 애플리케이션 종료 시 엔티티 매니저 팩토리도 종료해야 한다.

 

엔티티 매니저

- 엔티티를 데이터베이스에 CRUD할 수 있다.

- 데이터베이스 커넥션과 밀접한 관계가 있으므로 스레드 간 공유 또는 재사용하면 안 된다.

- 사용이 끝난 엔티티 매니저는 반드시 종료해야 한다.


비즈니스 로직

public class JpaMain {
    public static void main(String[] args) {

        ...

        try {
            tx.begin();
            logic(em); // 비즈니스 로직
            tx.commit();
        
        ...

    }

    private static void logic(EntityManager em) {

        ... // MEMBER 테이블에 저장할 member 객체 생성

        // 등록
        em.persist(member);

        // 수정
        member.setAge(20);

        // 조회(한 건)
        Member user1 = em.find(Member.class, id);
        log.info("user1 = `{}`", user1);
        
        // 조회(리스트)
        List<Member> members = em.createQuery("select m from Member m", Member.class)
                .getResultList();
        log.info("members size = {}", members.size());

        // 삭제
        em.remove(member);
    }
}

- em.persist() : 등록

- em.find() : 조회

- em.createQuery().getResultList() : 조회(리스트) => JPQL 사용

- em.remove() : 삭제

- JPA는 엔티티의 변경 사항을 추적하는 기능을 갖추고 있으므로 엔티티의 값을 변경해주기만 하면 자동으로 데이터베이스에 수정 내용이 반영된다.

 

JPQL

- JPA는 엔티티 객체를 대상으로 검색하기 때문에 데이터베이스 테이블의 모든 데이터를 대상으로 검색하는 것은 사실상 불가능하다. 이러한 경우에 JPA가 제공하는 JPQL(Java Persistence Query Language)을 사용하면 된다.

- JPQL은 SQL과 거의 유사한 문법을 가지고 있지만, 데이터베이스 테이블이 아닌 엔티티 객체를 대상으로 질의한다.

- JPQL은 대소문자를 명확하게 구분한다.

- JPQL은 데이터베이스 테이블을 전혀 알지 못한다. => 위의 코드에서 'from Member m'은 MEMBER 테이블이 아닌 엔티티 객체다.


트랜잭션 관리

public class JpaMain {
    public static void main(String[] args) {

        ...
        
        // 엔티티 매니저에서 트랜잭션 API를 받아온다.
        EntityTransaction tx = em.getTransaction();

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

    }
}

- 항상 트랜잭션 안에서 데이터를 변경해야 한다.


전체 코드

@Slf4j
public class JpaMain {
    public static void main(String[] args) {

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

        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 = "user1";
        Member member = new Member();
        member.setId(id);
        member.setUsername("yuri");
        member.setAge(30);

        em.persist(member);

        member.setAge(20);

        Member user1 = em.find(Member.class, id);
        log.info("user1 = `{}`", user1);
        
        List<Member> members = em.createQuery("select m from Member m", Member.class)
                .getResultList();
        log.info("members size = {}", members.size());

        em.remove(member);
    }
}