Backend/JPA
[JPA] Hello JPA
2245
2023. 12. 2. 20:15
서론
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
자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의
현업에서 실제로 JPA로 개발을 하고 있습니다. 그런 입장에서보면 지금 작성하고 있는 코드들이 어떻게 작동하는지 이해하는데 큰 도움을 주는 강의입니다. 다음은 제가 느낀 이 강의의 장점들
www.inflearn.com