오봉이와 함께하는 개발 블로그
JPA - 세팅, JPA&JPQL 개요 본문
728x90
세팅
- 메이븐 프로젝트를 사용
<dependencies>
<!-- JPA 하이버네이트 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.3.10.Final</version>
</dependency>
<!-- H2 데이터베이스 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
<!-- 자바11에서 나는 오류 해결용 -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
- JPA 설정을 위해서는 persistence.xml이 필요하다
- resources/META-INF/persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="hello">
<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=""/>
<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.hbm2ddl.auto" value="create" />-->
</properties>
</persistence-unit>
</persistence>
JPA 구동 방식
- 각각의 DB가 제공하는 SQL의 문법과 함수는 다르지만 JPA는 특정 DB에 종속하지 않는다
// persistence.xml에 있는 속성
// <persistence-unit name="값">
EntityManagerFactory emf = Persistence.createEntityManagerFactory("값");
EntityManager em = emf.createEntityManager();
// code
em.close();
emf.close();
객체와 테이블 생성 후 매핑
@Entity
@Getter
@Setter
public class Member {
@Id
private Long id;
private String name;
}
create table Member (
id bigint not null,
name varchar(255),
primary key (id)
);
- @Entity
- JPA가 관리할 객체
- @Id
- 데이터베이스 PK와 매핑
간단한 예제 코드(회원 등록)
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();
}
}
- 트랜잭션에 문제가 생겼을 경우를 대비해서 try-catch로 작성해야 한다.
- 오류가 생기면 엔티티 매니저가 닫히지 않기 때문.
- 또 오류가 생겼을 때 트랜잭션을 rollback할 수 있기 때문이다.
주의점!
- 엔티티 매니저 팩토리는 애플리케이션 로딩 시점에 딱 하나만 생성해서 애플리케이션 전체에서 공유한다.
- 엔티티 매니저는 쓰레드간 공유하지 않음.
- 사용하고 버려야 한다.
- DB에 접근해서 트랜잭션이 이뤄질 때는 무조건 엔티티 매니저를 만들어야 한다.
- 트랜잭션이 이뤄지고 무조건 close()를 해줘야 한다.
- JPA의 모든 데이터 변경은 트랜잭션 안에서 실행함.
궁금증
테이블 이름도, 컬럼 이름도 알려주지 않았는데 SQL이 정상적으로 실행됐다.
이는 관례에 따랐기 때문.
클래스 이름과 테이블 이름이 같고, 객체 이름과 컬럼 이름이 같아서 정상적으로 실행됨.
그럼 만약 다를 때는 어떻게 해야 할까?
@Entity
@Getter
@Setter
@Table(name = "user") // user 테이블에 매핑됨.
public class Member {
@Id
private Long id;
@Column(name = "username") // user 테이블의 username에 매핑됨
private String name;
}
간단한 예제 코드(회원 수정)
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 = em.find(Member.class, 1L);
member.setName("Hello Fix");
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
- find() 메소드로 객체를 찾아와서 저장 후, set을 사용해서 수정하면 자동으로 수정된다.
- 따로 저장하는 메소드를 사용하지 않았는데 어떻게 수정이 될까?
- JPA를 통해 엔티티를 가져오면 JPA가 관리한다.
- JPA가 관리하는 객체는 트랜잭션 커밋 시점에 변경을 감지해서 자동으로 쿼리를 날려 반영해준다.
- 이를 dirty checking이라 함.
- 따로 저장하는 메소드를 사용하지 않았는데 어떻게 수정이 될까?
간단한 예제 코드(회원 하나 조회)
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 = em.find(Member.class, 1L);
member.setName("Hello Fix");
System.out.println("member = " + member.getName());
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
간단한 예제 코드(회원 삭제)
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 = em.find(Member.class, 1L);
em.refresh(member);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
JPQL 소개
단순한 쿼리는 문제 없지만, 조금 복잡한 쿼리를 날릴 때는 JPQL을 사용해야 한다.
JPA는 엔티티 객체를 중심으로 개발하는데, 검색 쿼리를 날릴 때 문제가 발생한다.
검색할 때도 테이블이 아니라 엔티티 객체를 대상으로 검색하는데, 모든 DB 데이터를 객체로 변환해 검색하는 것은 불가능하다.
애플리케이션에서 필요한 데이터만 DB에서 불러오려면 검색 조건이 포함된 SQL이 필요한데, 이를 JPQL이 해결해 준다.
- JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어를 제공한다.
- SQL 문법과 유사하며, select, from, where, group by, having, join 지원함.
- JPQL은 엔티티 객체를 대상으로 쿼리
- 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리
- SQL을 추상화해서 특정 RDB에 의존하지 않는다
- 한마디로 정의하면 객체 지향 SQL
간단한 실습 예제 코드
전체 회원 검색
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 {
List<Member> result = em.createQuery("select m from Member as m", Member.class).getResultList();
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
출처 : 인프런 김영한 지식공유자님의 스프링 완전 정복 로드맵 강의
728x90
'BE > JPA' 카테고리의 다른 글
JPA - 실전 예제 1 - 요구사항 분석과 기본 매핑 (0) | 2022.06.24 |
---|---|
JPA - 필드와 컬럼 매핑, 기본 키 매핑 (0) | 2022.06.24 |
JPA - 객체와 테이블 매핑, DB 스키마 자동 생성 (0) | 2022.06.24 |
JPA - 플러시, 준영속 상태 (0) | 2022.06.23 |
JPA - 영속성 컨텍스트 (0) | 2022.06.23 |
Comments