JPQL
JPA를 활용하여 엔티티 객체를 중심으로 개발 한다.
검색하는 작업을 효율적으로 진행하기 위에 JPA는 JPQL 이라는 쿼리 언어로 SQL을 실행하도록 지원해준다.
틀
em.createQuery("JQL쿼리", JPQL에 사용되는 클래스타입);
예제
List<Member> result = em.createQuery("select m from Member as m", Member.class)
.setFirstResult(5)
.setMaxResults(8)
.getResultList();
JPQL이라는 객체지향 쿼리 언어를 제공
SQL 데이터베이스 테이블 대상으로 쿼리를 제공한다.
select m from Member as m SQL과 다르게 실제 엔티티가 from의 대상이 된다.
영속성 관리
JPA가 제공하는 기능
EntitiyMangerFactory 와 EntityManger
EntityMangerFactory
- 보통 데이터베이스 1개만 사용하는 애플리케이션은 일반적으로 EntityMangerFactory를 하나만 생성
EntityMangerFactory 생성방법
EntityManager em = emf.createEntityManager();
- 이름과 비슷하게 비용이 상당하다 때문에 1개만 만들어서 애플리케이션 전체에서 공유하도록 설계 해줘야 한다.
XML 방식) META-INF/persistence.xml
<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="1234"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/practiceJPA"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect"/>
<!-- 옵션 -->
<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>
- Persistence.createEntityManagerFactory("hello"); 를 호출하면 META-INF / persistence.xml에서 <persistence-unit name="hello"> 이라는 정보를 바탕으로 EntityManagerFactory를 생성한다.
엔티티 매니저
엔티티를 수정하고, 삭제, 조회 등 엔티티와 관련된 모든 일을 처리한다. 엔티티를 저장하는 가상의 데이터 베이스라고 생각해보자.
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
영속성 컨텍스트
- 엔티티를 영구 저장하는 환경
- 캐시와 같은 역할을 수행, 내부적으로 엔티티 보관
- EntityManger를 사용하면 영속성 켄텍스트에 엔티티 저장 및 조회
em.persist(member);
EntityManger 는 엔티티를 영속성 컨텍스트에 보관하고 관리
이후 commit이 일어나면 영속성 컨텍스트에서 쿼리 만들어 DB에 반영
비영속 : 영속성 컨텍스트와 전혀 관계가 없는상태
영속 : 영속성 컨텍스트에 저장된 상태
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
// 트랜잭션을 생성하고 시작하고
// commit 까지 하면 실행 됨
tx.begin();
// 객체.setName set을 활용하면 update
try{
//비영속 : 엔티티를 생성한 상태
Member member = new Member();
member.setId(100L);
member.setName("HelloJPA");
//영속
System.out.println("--BEFORE--");
//객체를 저장한 상태
em.persist(member);
System.out.println("--AFTER--");
//commit을 해야 DB에 저장이 된상태
tx.commit();
}catch(Exception e){
tx.rollback();
}finally {
em.close();
}
emf.close();
}
}
1차 캐시에서 조회
try{
//비영속
Member member = new Member();
member.setId(101L);
member.setName("HelloJPA");
//영속
System.out.println("--BEFORE--");
em.persist(member);
System.out.println("--AFTER--");
Member findMember = em.find(Member.class, 101L);
System.out.println("findMember.id = " + findMember.getId());
System.out.println("findMember.name = " + findMember.getName());
tx.commit();
}
데이터베이스에서 조회
- 영속 엔티티 동일성 보장
//영속
Member findMember1 = em.find(Member.class, 101L);
Member findMember2 = em.find(Member.class, 101L);
System.out.println("result == " + (findMember2 == findMember1));
tx.commit();
- 엔티티 등록
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 member1 = new Member(150L, "A");
Member member2 = new Member(160L,"B");
em.persist(member1);
em.persist(member2);
System.out.println("--------------");
// commit 하는 순간 데이터베이스에 insert sql을 보낸다
tx.commit();
}catch(Exception e){
tx.rollback();
}finally {
em.close();
}
emf.close();
}
}
- 엔티티 수정
try{
//영속
Member member = em.find(Member.class, 150L);
member.setName("ZZZZ");
em.persist(member);
System.out.println("--------------");
// commit 하는 순간 데이터베이스에 insert sql을 보낸다
tx.commit();
}
- 엔티티 삭제
플러시
영속성 컨텍스트의 변경내용을 DB에 반영
- FlushModeType.AUTO : 커밋이나 쿼리를 실행할 때 플러시(기본값)
- FlushModeType.COMMIT : 커밋할 때만 플러시
플러시라는 이름으로 인해 영속성 컨텍스트에 보관된 엔티티를 지운다고 생각 하면 안됨
트랜잭션 커밋 직전에만 변경 내용을 데이터베이스에 보내 동기화하면 된다
준영속 상태 특징
- 거의 비영속 상태에 가깝다
- 식별자 값을 가지고 있다 , 한 번 영속 상태를 갔다 왔기 때문에 ID값이 있다.
- 지연 로딩을 할 수 없다
병합
준영속 상태의 엔티티를 어떻게 다시 영속 상태로 만들까?
merge()메소드는 준영속 상태의 엔티티를 받아 새로운 영속 상태의 엔티티를 반환
최종
- 엔티티 매니저는 엔티티 매니저 팩토리에서 생성
- 영속성 컨텍스트는 엔티티 매니저를 통해 접근이 가능하고, 객체를 보관하는 가상의 데이터 베이스 역할을 한다.
- 영속성 컨텍스트에 저장한 엔티티는 플러시 시점에 데이터 베이스에 반영되고, 일반적으로 트랜잭션 커밋을 할때 영속성 컨텍스트가 플러시가 된다.
- 영속성 컨테스트가 관리하는 엔티티를 더 이상 관리하지 못하면, 준영속 상태의 엔티티라 부른다. 때문에 영속성 컨텍스트가 제공하는 기능들을 활용할 수 없다. (1차 쓰기 지연, 변경감지, 지연 로딩 등)
'정리노트 > JPA' 카테고리의 다른 글
자바 ORM 표준 JPA 프로그래밍 - 기본편 02 (0) | 2022.04.26 |
---|---|
자바 ORM 표준 JPA 프로그래밍 - 기본편 01 (0) | 2022.04.26 |