Back-End/JPA

[북스터디] 자바 ORM 표준 JPA 프로그래밍 : JPA 시작

newny 2024. 5. 19. 20:23
반응형

JPA가 제공하는 매핑 어노테이션


@Entity

클래스의 위에 붙여 사용한다. 해당 클래스를 테이블과 매핑한다고 JPA에게 알려주는 역할을 한다. @Entity 어노테이션이 사용된 클래스를 엔티티 클래스라고 한다.

 

@Table

엔티티 클래스에 매핑할 테이블 정보를 알려준다. name 속성을 이용하여 해당 이름을 가지고 있는 테이블과 매핑한다. @Table 어노테이션을 생략하면 클래스 이름을 테이블 이름으로 매핑한다.

 

@Id

엔티티 클래스의 해당 어노테이션이 붙은 필드를 기본키에 매핑한다. @Id 어노테이션이 사용된 필드를 식별자 필드라고 한다.

@Column

필드를 컬럼에 매핑한다. 해당 어노테이션이 생략된 경우 컬럼명과 같은 네임의 필드를 매핑한다.

 

 

 

 

데이터베이스 방언


 

SQL 표준을 지키지 않거나 특정 데이터베이스만의 고유한 기능을 JPA에서는 방언(Dialect)이라 한다. 이러한 방언들로 인해 데이터베이스 교체시 문제가 발생할 수 있는데 JPA 구현체들은 이런 문제를 해결할 수 있는 데이터베이스 방언 클래스를 제공한다.

따라서 데이터베이스가 변경되어도 애플리케이션 코드를 변경할 필요 없이 데이터베이스 방언만 교체하면 된다.

 

 

 

 

애플리케이션 개발


1. 엔티티 매니저 설정

 

public class JpaMain {
	public static void main(String[] args) {
    	// 엔티티 매니저 팩토리 - 생성
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");
        
        // 엔티티 매니저 - 생성
        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) {...}
}

 

 

엔티티 매니저 팩토리 생성

persistence.xml의 설정 정보를 토대로 엔티티 매니저 팩토리를 생성해야한다. 이때 Persistence 클래스는 엔티티 매니저 팩토리를 생성해서 JPA를 사용할 수 있게 준비한다.

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

이렇게 하면 persistence.xml에서 이름이 jpabook인 영속성 유닛을 찾아서 엔티티 매니저 팩토리를 생성한다.

persistence.xml을 기반으로 JPA를 동작시키기 위한 엔티티 매니저 팩토리를 생성하는 비용은 아주 크다. 

따라서 엔티티 매니저 팩토리는 애플리케이션 전체에 하나만 생성하여 공유하며 사용해야한다.

 

 

엔티티 매니저 생성

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

엔티티 매니저 팩토리에서 엔티티 매니저를 생성하며, 엔티티 매니저는 JPA의 대부분의 기능을 제공한다. (예 : 데이터베이스 등록/수정/삭제/조회)

엔티티 매니저는 데이터베이스 커넥션과 밀접한 관계가 있으므로 스레드간에 공유하거나 재사용하면 안 된다.

 

 

 

 

2. 트랜잭션 관리

JPA를 사용하면 항상 트랜잭션 안에서 데이터를 변경해야 한다. 트랜잭션 없이 데이터를 변경하면 예외가 발생한다.

// 트랜잭션 - 획득
EntityTransaction tx = em.getTransaction();

try {
    tx.begin(); // 트랜잭션 - 시작
    logic(em); // 비즈니스 로직 실행
    tx.commit(); // 트랜잭션 - 커밋
} catch (Exception e) {
    tx.rollback(); // 트랜잭션 - 롤백
}

 

 

 

 

3. 비즈니스 로직

public static void logic(EntityManager em) {
	String id = "id1";
    Member member = new Member();
    member.setId(id);
    member.setUsername("지한");
    member.setAge(2);
    
    // 등록
    em.persist(member);
    
    // 수정
    member.setAge(20);
    
    // 한 건 조회
    Member findMember = em.find(Member.class, id);
    
    // 목록 조회
    List<Member> members = 
    	em.createQuery("select m from Member m", Member.class).getResultList();
    
    // 삭제
    em.remove(member);
}

 

등록

엔티티를 저장하려면 엔티티 매니저의 persist() 메서드에 저장할 엔티티를 넘겨주면 된다.

JPA는 회원 엔티티의 매핑 정보를 분석해서 다음과 같은 SQL을 만들어 데이터베이스에 전달한다.

INSERT INTO MEMBER (ID, NAME, AGE) VALUES ('id1', '지한', 2)

 

수정

JPA는 어떤 엔티티가 변경되었는지 추적하는 기능을 갖추고있다. 따라서 member.setAge(20) 처럼 엔티티의 값만 변경하면 다음과 같은 UPDATE SQL을 생성한다.

UPDATE MEMBER SET AGE = 20, NAME = '지한'
WHERE ID = 'id1'

 

삭제

엔티티 매니저의  remove() 메서드를 사용하면 된다. JPA는 다음 DELETE SQL을 생성해서 실행한다.

DELETE FROM MEMBER WHERE ID = 'id1'

 

한 건 조회

find() 메서드는 조회할 엔티티 타입과 데이터베이스 테이블의 기본 키와 매핑한 식별자 값으로 엔티티 하나를 조회하는 가장 단순한 조회 메서드 이다. JPA는 다음 SELECT SQL을 생성해서 실행한다.

SELECT * FROM MEMBER WHERE ID = 'id1'

 

JPQL

// 목록 조회
List<Member> members = 
    em.createQuery("select m from Member m", Member.class).getResultList();

애플리케이션이 필요한 데이터만 데이터베이스에서 불러오려면 결국 검색 조건이 포함된 SQL을 사용해야 한다. JPA는 JPQL이라는 쿼리 언어로 해당 문제를 해결한다.

JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어를 제공한다. JPQL은 SQL문법과 거의 유사해서 SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 등을 사용할 수 있다. 둘의 가장 큰 차이점은 다음과 같다.

  • JPQL은 엔티티 객체를 대상으로 쿼리한다. (JPQL은 데이터베이스 테이블을 전혀 알지 못함)
  • SQL은 데이터베이스 테이블을 대상으로 쿼리한다.

JPQL을 사용하려면 먼저 em.createQuery(JPQL, 반환타입) 메서드를 실행해서 쿼리 객체를 생성한 후 쿼리 객체의 getResultList() 메서드를 호출하면 된다. JPA는 다음 SELECT SQL을 생성해서 실행한다.

SELECT M.ID, M.NAME, M.AGE FROM MEMBER M

 

 

 

 

결론


JPA가 반복적인 JDBC API와 결과 값 매핑을 처리해준 덕분에 코드량이 상당히 많이 줄어들었다.

또한 직접 SQL을 작성하지 않아도 된다.

 

 

 

 

출처

자바 ORM 표준 JPA 프로그래밍 - 김영한 지음 (에이콘 출판)

https://logical-code.tistory.com/m/126

https://bnzn2426.tistory.com/143

반응형