JPA - 구동방식
JPA - 구동방식
JPA를 쓰기전 필요한 설정
1. 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.jdbc.batch_size" value="10"/>
<property name="hibernate.hbm2ddl.auto" value="create" />
</properties>
</persistence-unit>
</persistence>
• persistence-unit name=?
: EntitiyManagerFactory를 생성하기 위해 필요한 이름.
• hibernate.dialect
: 어떤 데이터베이스를 사용할지 지정.
2. EntityManagerFactory 생성
하나만 생성해서 애플리케이션 전체에 서 공유한다.
EntityManagerFactory의 라이프 사이클은 Application의 라이플 사이클과 같다.
import javax.persistence.Persistence;
import javax.persistence.EntityManagerFactory;
EntityManagerFactory entityManagerFactory = persistence.createEntityManagerFactory("persistence-unit name")
3. EntityManger 생성
엔티티 매니저는 쓰레드간에 공유하지 않는다. (사용하고 버려야 한다).
EntityManger의 라이프 사이클은 HttpServletRequest의 라이프 사이클과 같다.
import javax.persistence.EntityManager;
EntityManager entityManager = emf.createEntityManager();
4. EntityManger, EntityManagerFactory 종료
entityManager.close();
entityManagerFactory.close();
Member 생성, 조회, 수정
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
@Getter @Setter
@NoArgsConstructor
@AllArgsConstructor
public class Member {
@Id
private Long id;
@Column(name="MEMBER_NM")
private String name;
}
Member member = new Member(1L,"Gilbert");
entityManager.persist(member);
이렇게 하면 에러가 발생한다.
왜냐면 JPA의 모든 데이터 변경은 트랜잭션 안에서 실행되어야 하기 때문이다.
따라서 아래와 같이 트랜잭션 관련된 코드를 추가해줘야 한다.
EntityTransaction tx = entityManager.getTransaction();
tx.begin();
try {
/* 생성
Member member = new Member(1L,"Gilbert");
entityManager.persist(member);
*/
/* 단일 조회
Member member = entityManager.find(Member.class, 1L);
*/
/* 컬렉션 조회 (JPQL)
Member member = em.createQuery("SELECT m FROM MEMBER AS m", Member.class)
.setFirstResult(5)
.setMaxResulsts(8)
.getResultList();
*/
/* 수정
Member member = entityManager.find(Member.class, 1L);
member.setName("gilbert")
*/
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
마지막 수정 부분을 자세히 봐보자.
Member member = entityManager.find(Member.class, 1L);
member.setName("gilbert")
마지막 줄에 entityManager.persist(member);
를 해줘야 DB에 반영된다고 생각할 수 있다.
하지만 위 코드를 작성하지 않아도 UPDATE 쿼리가 생성된다. 왜 그럴까??
JPA를 통해서 가져온 Entity는 JPA의 관리하에 들어간다고 한다. 그리고 데이터가 변경됐는지
안됐는지를 JPA가 다 주시하고 있다. 따라서 데이터가 변경이 됐다면, JPA는 트랜잭션 커밋
직전에 UPDATE 쿼리를 생성해 전달한다. 그리고 커밋이 이루어지고 DB에도 변경된 데이터가
정상적으로 반영된다.
JPQL
• 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리
• SQL을 추상화했기 때문에 특정 데이터베이스 SQL에 의존하지 않는다.
• JPQL을 한마디로 정의하면 객체 지향 SQL 이라고 할 수 있다.