728x90
프로젝트 생성
인텔리제이 → File → new → project... → maven
1. 메이븐 라이브러리 - pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>jpa-basic</groupId>
<artifactId>ex1-hello-jpa</artifactId>
<version>1.0.0</version>
<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.199</version>
</dependency>
</dependencies>
</project>
2. JPA 설정 - 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>
- 파일 위치
- resureces/META-INF/persistence.xml
- persistence-unit name을 hello로 지정
3. JPA는 특정 데이터베이스에 종속되지 않는다.
- JPA는 특정 데이터베이스에 종속되지 않는다.
- hibernate.dialect 속성으로 데이터베이스 방언을 지정할 수 있다.
- 데이터베이스 방언 : SQL 표준을 지키지 않는 특정 데이터베이스만의 고유한 기능
- H2 : org.hibernate.dialect.H2Dialect
- Oracle 10g : org.hibernate.dialect.Oracle12cDialect
- MySQL : org.hibernate.dialect.MySQL5Dialect
- 하이버네이트는 40가지 이상의 데이터베이스 방언을 지원한다.
4. JPA 구동 방식 - maven
- 엔티티 매니저 팩토리(EntityManagerFactory)는 하나만 생성해서 애플리케이션 전체에서 공유한다.
- 엔티티 매니저(EntityManager)는 쓰레드간에 공유하면 안된다. (사용하고 버려야 한다.)
- 고객의 요청이 올 때마다 엔티티 매니저를 쓰고 버린다. 재사용 x
- JPA의 모든 데이터 변경은 트랜잭션(Transaction) 안에서 실행해야 한다.
5. 객체, 테이블 생성 후 매핑
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 void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- @Entity : JPA가 관리할 객체
- @Id : 데이터베이스 PK와 매핑
테이블 생성
create table Member (
id bigint not null,
name varchar(255),
primary key (id)
);
6. 실습
회원 등록
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
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(2L);
member.setName("HelloB");
em.persist(member);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
회원 수정
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
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);
findMember.setName("HelloJPA");
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
- 저장된 데이터를 수정할 때는 자바 컬렉션처럼 수정된 객체를 다시 저장하지 않아도 된다.
- find 메서드를 통해서 가져온 객체의 값을 setter 메서드로 필드 값을 변경한다. 그러면 commit() 호출 시 적용되기 전 시스템에서 변경감지를 통해 기존 객체와 차이점을 찾아서 업데이트를 자동으로 해준다.
회원 삭제
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
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();
}
}
회원 단 건 조회
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
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);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
7. JPQL 소개
- JPQL은 JPA에서 제공하는 객체지향 쿼리다.
- 테이블이 아닌 엔티티 객체를 대상으로 검색한다.
- SQL을 추상화해서 특정 데이터베이스 SQL에 의존하지 않는다.
- JPA는 JPQL을 분석한 후 적절한 SQL을 만들어 데이트베이스를 조회한다.
- 식별자를 통한 단순 조회가 아닌 추가 조건들을 통해 조회를 하고자 할 때 사용된다.
- JPA에서 단순 PK값으로만 find() 하는 것이 아니기 때문에 여러가지 조건으로 검색하는 쿼리를 위해 JPQL이 필요하다.
- 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능하기 때문이다.
- 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요하다.
- SQL과 문법이 유사하다. SELECT / FROM / WHERE / GROUP BY / HAVING / JOIN 문법을 지원한다.
회원 전체조회
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
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();
}
}
- 테이블이 아닌 엔티티 객체를 대상으로 검색한다.
- 일반 쿼리와 다르게 From 절의 Member는 테이블이 아닌 엔티티(Member.class)를 대상으로 한다.
테이블이 아닌 엔티티를 사용한 쿼리의 장점은?
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
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)
.setFirstResult(5) // JPQL 페이징 처리
.setMaxResults(8) // JPQL 페이징 처리
.getResultList();
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
- 페이징처리를 할 때 각 DB의 방언에 따라 지원하는 메서드가 다르다.
- 하지만 JPQL을 사용하 DB를 바꿔도 JPQL 코드를 바꾸지 않아도 된다.
🧷 (참고) Querydsl
- Querydsl은 JPQL을 편하게 작성할 수 있게 도와주는 JPQL 빌더 역할을 한다.
- Querydsl은 오픈 소스이므로 라이브러리를 설치해야 한다.
- Querydsl은 자바 코드이기 때문에 컴파일 시점에서 에러를 잡을 수 있어서 좋다.
Querydsl 기본 문법
Querydsl vs JPQL
- 복잡한 쿼리나 동적쿼리를 사용할 때 Querydsl을 사용한다.
- 진짜 매우 단순한 경우에만 JPQL로 작성한다.
- 사실상 대부분 쿼리를 Querydsl로 작성해야한다고 보면 된다.
👀 참고 자료
https://www.inflearn.com/course/ORM-JPA-Basic/dashboard
https://catsbi.oopy.io/0a48ff61-ee46-4909-b5b4-d5f63937195f
https://developer-minji.tistory.com/m/87
https://www.inflearn.com/questions/38771
728x90
'[JPA] > JPA 프로그래밍 - 기본편' 카테고리의 다른 글
[JPA] 다양한 연관관계 매핑 (0) | 2022.03.29 |
---|---|
[JPA] 연관관계 매핑 기초 (0) | 2022.03.28 |
[JPA] 엔티티 매핑 (0) | 2022.03.27 |
[JPA] 영속성 관리 - 내부 동작 방식 (0) | 2022.03.26 |
[JPA] SQL 중심적인 개발의 문제점과 JPA 소개 (0) | 2022.03.26 |