간단한 애플리케이션 개발
이전 글에서 작성한 내용을 이어서 보면 된다.
public class JpaMain {
public static void main(String[] args) {
// 엔티티 매니저 팩토리 생성
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa_practice");
// 엔티티 매니저 생성
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("지한");
member.setAge(2);
// 등록
em.persist(member);
// 수정
member.setAge(20);
// 한 건 조회
Member findMember = em.find(Member.class, id);
System.out.println("findMember="+ findMember.getUsername()+", age="+findMember.getAge());
// 목록 조회
List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();
System.out.println("members.size="+members.size());
// 삭제
em.remove(member);
}
}
코드는 크게 3부분으로 나뉘어 있다.
1.엔티티 매니저 설정
JPA를 시작하려면 우선 persistence.xml의 설정 정보를 사용해서 엔티티 매니저 팩토리를 생성해야 한다.
// 엔티티 매니저 팩토리 생성
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa_practice");
이렇게 하면 이전 글에서 작성한 persistence.xml에서 jpa_practice라는 영속성 유닛을 찾아서 엔티티 매니저 팩토리를 생성한다.
이 때 persistence.xml의 설정 정보를 읽어서 JPA를 동작시키기 위한 기반 객체를 만들고 JPA 구현체에 따라서는 데이터베이스 커넥션 풀도 생성하므로 엔티티 매니저 팩토리를 생성하는 비용은 아주 크다.
따라서 엔티티 매니저 팩토리는 애플리케이션 전체에서 딱 한 번만 생성하고 공유해서 사용해야 한다.
// 엔티티 매니저 생성
EntityManager em = emf.createEntityManager();
엔티티 매니저 팩토리에서 엔티티 매니저를 생성한다. JPA의 기능 대부분은 이 엔티티 매니저가 제공한다. 대표적으로 엔티티 매니저를 사용해서 엔티티를 데이터베이스에 등록/수정/삭제/조회할 수 있다.
엔티티 매니저는 내부에 데이터소스(db커넥션)를 유지하면서 데이터베이스와 통신한다.
참고로 엔티티 매니저는 데이터베이스 커넥션과 밀접한 관계가 있으므로 스레드간에 공유하거나 재사용하면 안 된다.
// 엔티티 매니저 종료
em.close();
// 엔티티 매니저 팩토리 종료
emf.close();
마지막으로 사용이 끝난 엔티티 매니저는 다음처럼 반드시 종료해야 한다.
애플리케이션을 종료할 때 엔티티 매니저 팩토리도 다음처럼 종료해야 한다.
2.트랜잭션 관리
JPA를 사용하려면 항상 트랜잭션 안에서 데이터를 변경해야 한다.
트랜잭션 없이 데이터를 변경하면 예외가 발생한다.
트랜잭션을 시작하려면 엔티티 매니저에서 트랜잭션 API를 받아와야 한다.
// 트랜잭션 획득
EntityTransaction tx = em.getTransaction();
try {
tx.begin(); // 트랜잭션 - 시작
logic(em); // 비지니스 로직 실행
tx.commit(); // 트랜잭션 커밋
} catch (Exception e){
tx.rollback(); // 트랜잭션 - 롤백
}
트랜잭션 API를 사용해서 비지니스 로직이 정상 동작하면 트랜잭션을 커밋하고 예외가 발생하면 트랜잭션을 롤백한다.
3.비지니스 로직
private 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);
System.out.println("findMember="+ findMember.getUsername()+", age="+findMember.getAge());
// 목록 조회
List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();
System.out.println("members.size="+members.size());
// 삭제
em.remove(member);
}
비지니스 로직을 보면 등록, 수정, 삭제, 조회 작업이 엔티티 매니저(em)를 통해서 수행되는 것을 알 수 있다. 엔티티 매니저는 객체를 저장하는 가상의 데이터베이스처럼 보인다.
등록
String id = "id1";
Member member = new Member();
member.setId(id);
member.setUsername("지한");
member.setAge(2);
// 등록
em.persist(member);
엔티티를 저장하려면 엔티티 매니저의 persist() 메소드에 저장할 엔티티를 넘겨주면 된다. JPA는 회원 엔티티의 매핑 정보를 분석해서 다음과 같은 SQL을 만들어 데이터베이스에 전달한다.
INSERT INTO MEMBER (ID,NAME,AGE) VALUES('id1','지한',2)
수정
// 수정
member.setAge(20);
JPA는 어떤 엔티티가 변경되었는지 추적하는 기능을 갖추고 있다. 따라서 member.setAge(20) 처럼 엔티티의 값만 변경하면 다음과 같은 SQL을 생성해서 실행한다.
UPDATE MEMBER SET AGE = 20 WHERE ID = 'id1'
삭제
// 삭제
em.remove(member);
엔티티를 삭제하려면 엔티티 매니저의 remove() 메소드에 삭제하려는 엔티티를 넘겨준다. JPA는 다음 SQL을 생성해서 실행한다.
DELETE FROM MEMBER WHERE ID = 'id1'
조회
한 건 조회
// 한 건 조회
Member findMember = em.find(Member.class, id);
find() 메소드는 조회할 엔티티 타입과 @Id로 데이터베이스 테이블의 기본 키와 매핑한 식별자 값으로 엔티티 하나를 조회하는 가장 단순한 조회 메소드이다. 다음 SQL을 생성해서 실행한 후 결과 값을 반환한다.
SELECT * FROM MEMBER WHERE ID = 'id1'
목록 조회
// 목록 조회
List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();
JPA를 사용하면 애플리케이션 개발자는 엔티티 객체를 중심으로 개발하고 데이터베이스에 대한 처리는 JPA에 맡겨야 한다.
앞서 살펴본 등록, 수정, 삭제, 한 건 조회는 SQL을 사용하지 않았다.
문제는 검색 쿼리이다. 테이블이 아닌 엔티티 객체를 대상으로 검색하려면 데이터베이스의 모든 데이터를 애플리케이션으로 불러와서 엔티티 객체로 변경한 다음 검색해야 하는데, 이는 사실상 불가능하다.
애플리케이션이 필요한 데이터만 데이터베이스에서 불러오려면 결국 검색 조건이 포함된 SQL을 사용해야 한다. JPA는 JPQL(Java Persistence Query Language)이라는 쿼리 언어로 이런 문제를 해결한다.
JPQL은 SQL과 문법이 거의 유사하다.
JPQL 과 SQL과의 차이점
1.JPQL은 엔티티 객체를 대상으로 쿼리한다. 즉 클래스와 필드를 대상으로 쿼리한다.
2.SQL은 데이터베이스 테이블을 대상으로 쿼리한다.
위 쿼리에서 select m from member m 이 바로 JPQL이다. 여기서 member는 테이블이 아닌 회원 엔티티 객체를 말하는 것이다.
JPQL을 사용하려면 먼저 em.createQuery(JPQL 반환 타입)메소드를 실행해서 쿼리 객체를 생성한 후 쿼리 객체의 getResultList() 메소드를 호출하면 된다.
'스프링 > JPA' 카테고리의 다른 글
2.JPA 시작(1) (0) | 2023.12.27 |
---|---|
1.JPA란 무엇인가? (2) | 2023.12.26 |
댓글