서론
JPA 의 구동 방식과 간단한 예제를 통해 코드를 알아보고, JPQL에 관해 간략하게 설명하는 글입니다.
Hello JPA
JPA 구동 방식
- JPA는 Persistence라는 클래스에서 시작을 합니다.
- Persistence는 설정 파일을 통해 설정 정보를 조회합니다.
- 설정 정보에 따라, EntityManagerFactory 라는 클래스를 생성합니다.
- 해당 클래스에서 필요할 때마다 EntityManager를 찍어냅니다.
실습
기본
package hellojpa;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
//code
em.close();
emf.close();
}
}
- EntityManagerFactory는 애플리케이션 로딩 시점에 한 개만 생성해야 합니다.
- 트랜잭션마다, 즉 DB에서 connection을 얻어 쿼리를 날리고 종료되는 일련의 행위마다 EntityManager를 항상 생성해야 합니다.
- 사용 후 객체를 반납해야 합니다.
객체와 테이블을 생성하고 매핑하기
- @Entity: JPA가 관리할 객체
- @Id: 데이터베이스 PK와 매핑
package hellojpa;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Member {
@Id
private Long id;
private String name;
public Long getId() {
return id;
}
public String getName() {
return name;
}
public void setId(Long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
}
create table Member (
id bigint not null,
name varchar(255),
primary key (id)
);
회원 등록
package hellojpa;
...
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Member member = new Member();
member.setId(1L);
member.setName("helloA");
em.persist(member);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
[결과]
Hibernate:
/* insert hellojpa.Member
*/ insert
into
Member
(name, id)
values
(?, ?)
회원 단 건 조회
package hellojpa;
...
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Member findMember = em.find(Member.class, 1L);
System.out.println("findMember.id = " + findMember.getId());
System.out.println("findMember.name = " + findMember.getName());
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
Hibernate:
select
member0_.id as id1_0_0_,
member0_.name as name2_0_0_
from
Member member0_
where
member0_.id=?
회원 수정
package hellojpa;
...
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Member findMember = em.find(Member.class, 1L);
System.out.println("findMember.id = " + findMember.getId());
System.out.println("findMember.name = " + findMember.getName());
findMember.setName("HelloA");
System.out.println("findMember.id = " + findMember.getId());
System.out.println("findMember.name = " + findMember.getName());
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
Hibernate:
select
member0_.id as id1_0_0_,
member0_.name as name2_0_0_
from
Member member0_
where
member0_.id=?
findMember.id = 1
findMember.name = helloA
Hibernate:
/* update
hellojpa.Member */ update
Member
set
name=?
where
id=?
findMember.id = 1
findMember.name = HelloA
회원 삭제
package hellojpa;
...
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Member findMember = em.find(Member.class, 1L);
em.remove(findMember);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
Hibernate:
/* delete hellojpa.Member */ delete
from
Member
where
id=?
💡주의
- 엔티티 매니저 팩토리는 하나만 생성해서 애플리케이션 전체에서 공유해서 사용합니다.
- 엔티티 매니저는 쓰레드간에 공유X (커넥션을 한 번 사용하고 버리듯이, 엔티티 매니저도 한 번 사용하고 버려야 합니다.)
- JPA의 모든 데이터 변경은 트랜잭션 안에서 실행합니다.
JPQL 소개
가장 단순한 조회 방법은 위에서 봤던 EntityManger.find()입니다. 객체 그래프 탐색(a.getB().getC())을 통해 조회할 수 있습니다. 하지만 만약, 나이가 18살 이상인 회원을 모두 검색하는 조금 복잡한 SQL을 작성해야 할 경우 어떻게 해결할 수 있을까요? JPQL을 통해 해결할 수 있습니다.
실습
JPQL로 전체 회원 검색
List<Member> result = em.createQuery("select m from Member as m", Member.class)
.getResultList();
- JPQL에서 대상은 테이블이 아닌 객체입니다.
- JPQL을 사용하면 페이징과 같이 복잡한 쿼리문을 객체를 대상으로 자바를 사용하여 간편하게 작성할 수 있습니다.
특징
- JPA를 사용하면 엔티티 객체를 중심으로 개발
- 문제는 검색 쿼리
- 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색
- 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능
- 애플리케이션이 필요한 데이터만 DB에서 불러오려면, 결국 검색 조건이 포함된 SQL이 필요
- JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어 제공
- SQL과 문법 유사, SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원
- JPQL은 엔티티 객체를 대상으로 쿼리
- SQL은 데이터베이스 테이블을 대상으로 쿼리
- 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리
- SQL을 추상화해서 특정 데이터베이스 SQL에 의존X
- JPQL을 한마디로 정의하면 객체 지향 SQL
출처
https://www.inflearn.com/course/ORM-JPA-Basic/dashboard
'Backend > JPA' 카테고리의 다른 글
[JPA] 다양한 연관관계 매핑 (0) | 2023.12.18 |
---|---|
[JPA] 연관관계 매핑 (0) | 2023.12.18 |
[JPA] 엔티티 매핑 (0) | 2023.12.18 |
[JPA] 영속성 컨텍스트 (0) | 2023.12.18 |
[JPA] JPA 소개 (0) | 2023.12.01 |