컴공댕이 공부일지
[JPA] 2장 - JPA 시작 본문
본 글은 도서 '자바 ORM 표준 JPA 프로그래밍'의 2장 요약 정리본입니다.
📖 라이브러리와 프로젝트 구조
메이븐 - 라이브러리 관리해주는 도구.
pom.xml( → 메이븐 설정파일)에 사용할 라이브러리 작성하면 라이브러리 자동으로 내려받아 관리
하이버네이트( → JPA를 실제로 구현한 대표적인 구현체 ) 핵심 라이브러리
- hibernate-core : 하이버네이트 라이브러리 ; 가장 기본적인 ORM 기능 제공
- hibernate-jpa-2.1-api : JPA 2.1 표준 API를 모아둔 라이브러리 ; 이러케 동작해야한다는 인터페이스 제공. 명세, 룰
- hibernate-entitymanager : 하이버네이트가 JPA 구현체로 동작하도록 JPA 표준을 구현한 라이브러리 ; JPA와 함께 사용할 때 필요
pom.xml 중 일부. dependencies : 사용할 라이브러리 지정.
<dependencies>
<!-- JPA, 하이버네이트 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- H2 데이터베이스 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2db.version}</version>
</dependency>
</dependencies>
groupId, artifactId, version만 적어두면,
라이브러리를 메이븐 공식 저장소에서 내려받아 라이브러리에 추가
📝 객체 매핑
매핑 어노테이션
| 어노테이션 | 설명 |
| @Entity | 이 클래스를 테이블과 매핑한다고 JPA에 알려줌 @Entity가 사용된 클래스=엔티티 클래스 |
| @Table | 엔티티 클래스에 매핑할 테이블 정보를 알려줌 |
| @Id | 필드를 기본 키에 매핑 @Id가 사용된 필드=식별자 필드 |
| @Column | 필드를 DB 컬럼에 매핑함 |
| 매핑 정보가 없는 필드 | 매핑 어노테이션을 생략하면 필드명을 사용해서 컬럼명으로 매핑 @Column이 없어도 JPA가 자동 매핑 |
= JPA가 매핑 어노테이션을 분석해 어떤 객체가 어떤 테이블과 관계가 있는지 알아냄.
어떤 엔티티를 어떤 테이블에 저장해야 할 지 알게됨.
⚙️ persistence.xml - JPA 설정
persistence.xml 설정 - JPA 환경설정 파일
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
<persistence-unit name="jpabook"> -- 연결할 DB 당 하나의 영속성 유닛을 등록하는 것이 일반적.
<properties>
<!-- 필수 속성 -->
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/> -- sa 계정 비밀번호
<property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<!-- 옵션 -->
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.use_sql_comments" value="true" />
<property name="hibernate.id.new_generator_mappings" value="true" />
<!--<property name="hibernate.hbm2ddl.auto" value="create" />-->
</properties>
</persistence-unit>
</persistence>
- 사용한 속성들
JPA 표준 속성 (특정 구현체에 종속되지 않음)
- javax.persistence.jdbc.driver : JDBC 드라이버
- javax.persistence.jdbc.user : 데이터베이스 접속 아이디
- javax.persistence.jdbc.password : 데이터베이스 접속 비밀번호
- javax.persistence.jdbc.url : 데이터베이스 접속 URL
하이버네이트 속성
- hibernate.dialect : 데이터베이스 방언 설정
- hibernate.show_sql : 하이버네이트가 실행한 SQL 출력
- hibernate.format_sql : 하이버네이트가 실행한 SQL을 보기 좋게 정렬
- hibernate.use_sql_comments : 쿼리를 출력할 때 주석도 함께 출력
- hibernate.id.new_generator_mappings : JPA 표준에 맞춘 새로운 키 생성 전략 사용
🗣️ 데이터베이스 방언
SQL 표준을 지키지 않거나 특정 DB만의 고유한 기능
- 대부분의 JPA 구현체들은 다양한 데이터베이스 방언 클래스를 제공
특정 DB에 종속되는 기능을 사용한 경우에도, DB 교체 수월하도록. DB와 독립적이도록 ! - 개발자는 JPA가 제공하는 표준 문법에 맞추어 JPA를 사용하면 되고, 특정 데이터베이스에 의존적인 SQL은 데이터베이스 방언이 알아서 처리해줌
- 데이터베이스가 변경되면 데이터베이스 방언만 교체하면 됨
- 하이버네이트가 제공하는 데이터베이스 방언
- H2 : org.hibernate.dialect.H2Dialect
- 오라클 10g : org.hibernate.dialect.Oracle10gDialect
- MySQL : org.hibernate.dialect.MySQL5InnoDBDialect
package jpabook.start;
import javax.persistence.*;
import java.util.List;
/**
* @author holyeye
*/
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) {
e.printStackTrace();
tx.rollback(); //트랜잭션 롤백
} finally {
em.close(); //엔티티 매니저 종료
}
emf.close(); //엔티티 매니저 팩토리 종료
}
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);
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);
}
}
1️⃣ 엔티티 매니저 설정
- 앤티티 매니저 팩토리 ; 엔티티 매니저 생성하는 공장
persistence.xml의 설정 정보 읽어, 영속성 유닛을 찾아 엔티티 매니저 팩토리 생성
데이터베이스 연결 풀을 관리하므로 무분별하게 생성하면 성능 저하가 발생
→ 한 번만 생성해서 공유해 사용할 것 !
어플리케이션 종료 시 엔티티 매니저 팩토리도 종료 emf.close()
- 앤티티 매니저 ; JPA 동작시키기 위한 기본 객체
실제 DB와 상호작용하는 객체 ▶ 데이터베이스 작업(저장, 수정, 삭제, 조회 등)을 수행하는 객체
→ DB 커넥션과 밀접한 관계가 있으므로, 각 스레드에서 독립적으로 사용.
→ 스레드 간에 공유X 재사용X
사용이 끝난 엔티티 매니저는 반드시 종료할 것. em.close()
2️⃣ *트랜잭션 관리
*트랜잭션 : 데이터베이스에서 일련의 작업을 하나의 단위로 묶어 처리하는 것
트랜잭션 안에서 수행된 모든 작업은 모두 성공해야만 데이터베이스에 반영되고,
하나라도 실패 시 전체 작업이 취소됨.
→ 데이터의 일관성을 보장하고, 원자성을 유지함.
JPA에서 데이터 변경 작업은 항상 트랜잭션 안에서 수행해야 함.
엔티티 매니저에서 트랜잭션 API 받아와서,
EntityTransaction tx = em.getTransaction();
commit( → 비지니스 로직 정상 동작)과 rollback( → 예외 발생) 등을 사용함.
3️⃣ 비즈니스 로직
등록 : persist(entity)
//등록
em.persist(member);
수정 : update() 메서드 없음, 엔티티 속성 직접 변경
//수정
member.setAge(20);
삭제 : remove(entity)
//삭제
em.remove(member);
조회 : find(entityClass, primaryKey), 엔티티(실제 데이터 ex. member)의 클래스 타입과 기본키로 조회
//한 건 조회
Member findMember = em.find(Member.class, id);
System.out.println("findMember=" + findMember.getUsername() + ", age=" + findMember.getAge());
//목록 조회 - JPLQ 쿼리로 Member 엔티티 객체 목록 반환
List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();
System.out.println("members.size=" + members.size());
⭐ JPQL (Java Persistence Query Language)
JPA에서 사용되는 객체 지향 쿼리 언어
DB의 테이블 대신 엔티티 객체를 기반으로 쿼리를 작성
JPA는 엔티티 객체를 중심으로 설계
검색 시 데이터베이스 테이블이 아니라 엔티티 객체를 대상으로 쿼리해야 함
모든 데이터를 애플리케이션에 불러와 엔티티로 변환한 후 검색하는 것은 불가능 !
JPQL은 객체 지향 쿼리 언어
SQL과 비슷. 데이터베이스 테이블이 아닌 엔티티 객체를 대상으로 쿼리
그래서 JPQL은 DB의 테이블을 전혀 알지 못한다 !
SQL은 데이터베이스 테이블을 대상으로 직접 쿼리하는 방식이다.
위의 비지니스 로직에도 JPQL 쿼리가 쓰였다.
아직은 익숙하지 않아서.. 아래는 좀 더 찾아 본 JPQL 쿼리 예시들

+ JPA의 이점
1. 객체 지향적인 데이터 관리
- JPA는 데이터베이스 테이블을 자바 객체(엔티티)로 매핑하여 객체 지향 프로그래밍 패러다임을 따릅니다.
- JPQL은 SQL과 유사하지만, 데이터베이스 테이블이 아닌 엔티티 객체를 대상으로 쿼리하므로 객체 지향적인 데이터 관리가 가능합니다.
2. 생산성 향상
- JPA는 복잡한 데이터베이스 작업을 추상화하여 개발자가 비즈니스 로직에 집중할 수 있도록 도와줍니다.
em.remove(member); ▶ JPA가 SQL 생성해 실행. DELETE FROM MEMBER WHERE ID = "id1"; - JPQL은 SQL보다 간결하고 명확한 쿼리 작성을 가능하게 하여 개발 생산성을 향상시킵니다.
3. 유지보수성 향상
- JPA는 데이터베이스 스키마 변경 시 엔티티 매핑만 수정하면 되므로 코드 수정 범위를 최소화합니다.
- JPQL은 데이터베이스에 독립적이므로 데이터베이스 종류가 변경되더라도 쿼리를 수정할 필요가 없습니다.
4. 데이터베이스 독립성
- JPA는 다양한 데이터베이스 시스템을 지원하므로 특정 데이터베이스에 종속되지 않습니다.
- JPQL은 JPA 구현체에 의해 각 데이터베이스에 맞는 SQL로 변환되므로 데이터베이스 종류에 상관없이 동일한 JPQL 쿼리를 사용할 수 있습니다.
5. 성능 최적화
- JPA는 영속성 컨텍스트, 1차 캐시, 지연 로딩 등 다양한 성능 최적화 기능을 제공합니다.
- JPQL은 필요한 데이터만 조회하도록 쿼리를 최적화하여 데이터베이스 성능을 향상시킬 수 있습니다.
6. 코드 가독성 향상
- JPQL은 SQL보다 간결하고 명확한 쿼리를 작성할 수 있어 코드 가독성을 높입니다.
- JPQL은 엔티티 간의 관계를 활용하여 복잡한 쿼리를 쉽게 작성할 수 있습니다.
7. 타입 안전성
- JPQL은 컴파일 시점에 쿼리 오류를 검출하여 런타임 오류를 방지합니다.
- JPQL은 엔티티 타입을 명시하므로 타입 안전성을 보장합니다.
2장 요약
JPA 사용 개발 환경 설정 진행.
객체 하나를 테이블에 등록/수정/삭제/조회 하는 애플리케이션 제작
JPA가 반복적인 JDBC API와 결과 값 매핑 처리 -> 코드 줄고, sql 작성할 필요 x
'study > 웹개발 스터디 백엔드 EFUB 💻' 카테고리의 다른 글
| [JPA] 10장 - 객체지향 쿼리 언어(1) (3) | 2025.05.26 |
|---|---|
| [JPA] 6장 - 다양한 연관관계 매핑 (0) | 2025.04.11 |
| [JPA] 5장 - 연관관계 매핑 기초 (0) | 2025.04.03 |
| [JPA] 4장 - 엔티티 매핑 (0) | 2025.03.30 |
| [JPA] 1장 - JPA 소개 (0) | 2025.03.16 |