[JPA] JPA 구동 방식과 간단 실습(CRUD)
자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의
이 글은 인프런에서 제공하는 자바 ORM 표준 JPA 프로그래밍 - 기본편 강의를 참고했고
강의 내용을 다시 복습하면서 정리하려는 목적으로 작성합니다.
2023.02.08 - [0 + 프로그래밍/0 + JPA] - [JPA] JPA 기초
JPA
는 JAVA Application
과 JDBC API
사이에서 동작한다는 것을 지난시간에 배웠습니다.
기본적으로 JPA
는 Persistence
라는 클래스로 시작하고 먼저 설정 정보를 조회하여 EntityManagerFactory
라는 클래스를 생성합니다.
그리고 EntityManagerFactory
에서 필요할때 마다 EntityManager
를 생성하여 사용합니다.
이를 그림으로 표현하면 아래와 같습니다.
기본적인 개념을 알았으니 실습을 진행해 볼까요?
실습 설정
H2 DataBase 설치 및 설정
H2 Database Engine
H2 DataBase 두번째 새 저장소 만들기(create a new database)
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="pureJpa">
<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="123"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/./pure-jpa"/>
<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>
persistence.xml
의 경로는 다음과 같습니다.
JpaMain
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("pureJpa");
}
}
메인 메소드를 생성하여 잘 동작하는지 확인 합니다.
실습 -회원(CRUD)
EntityManagerFactory
는 하나만 생성하여 애플리케이션 전체에서 공유 해야합니다.EntityManager
는 쓰레드간 공유하면 안됩니다.(사용하고 반드시 버려야 합니다.)JPA
의 모든 데이터 변경은 트랜잭션 안에서 실행해야 합니다.
먼저 회원 Entity
를 작성하겠습니다.
Member
@Entity
@Getter // 롬복 사용
public class Member {
@Id // PK
private Long id;
private String name;
public void changeName(String name) {
this.name = name;
}
}
Entity
는 DB TABLE
에 매핑
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="pureJpa">
<class>com.study.purejpa.entity.Member</class>
<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="123"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/./pure-jpa"/>
<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>
<class>com.study.purejpa.entity.Member</class>
을 추가 합니다.
JpaMain
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("pureJpa");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction(); // 트랜잭션 얻음
tx.begin(); // 트랜잭션 시작
try {
Member member = new Member();
member.setId(1L);
member.setName("아이유");
em.persist(member);
tx.commit(); // 커밋
} catch (Exception e) {
tx.rollback();
} finally {
em.close(); // DB Connection을 사용하여 작업함
}
emf.close(); // 애플리케이션이 종료되면 닫아야함
}
}
결과
오우오우오우!! 신기하지 않습니까? 🕺
쿼리가 자동 생성되었습니다.create table Member ( … )
쿼리가 발생한 이유는 persistence.xml
에서<property name="hibernate.hbm2ddl.auto" value="create" />
같이 설정했기 때문 입니다.
H2 console
에서도 확인 할수 있습니다.
조회
private static Member findMember(Long id, EntityManager em, EntityManagerFactory emf) {
EntityTransaction tx = em.getTransaction(); // 트랜잭션 얻음
Member member = null;
tx.begin(); // 트랜잭션 시작
try {
member = em.find(Member.class, id); // 조회
tx.commit(); // 커밋
} catch (Exception e) {
tx.rollback(); // 롤백
} finally {
em.close(); // DB Connection을 사용하여 작업함
}
emf.close(); // 애플리케이션이 종료되면 닫아야함
return member;
}
member = em.find(Member.class, id); // 조회
저장
private static void saveMember(Member member, EntityManager em, EntityManagerFactory emf) {
EntityTransaction tx = em.getTransaction(); // 트랜잭션 얻음
tx.begin(); // 트랜잭션 시작
try {
em.persist(member); // 저장
tx.commit(); // 커밋
} catch (Exception e) {
tx.rollback(); // 롤백
} finally {
em.close(); // DB Connection을 사용하여 작업함
}
emf.close(); // 애플리케이션이 종료되면 닫아야함
}
em.persist(member); // 저장
삭제
private static void deleteMember(Long id, EntityManager em, EntityManagerFactory emf) {
EntityTransaction tx = em.getTransaction();
tx.begin(); // 트랜잭션 시작
try {
Member findMember = em.find(Member.class, id);
em.remove(findMember); // 삭제
tx.commit(); // 커밋
} catch (Exception e) {
tx.rollback(); // 롤백
} finally {
em.close(); // DB Connection을 사용하여 작업함
}
emf.close(); // 애플리케이션이 종료되면 닫아야함
}
em.remove(findMember); // 삭제
수정
private static void updateMemberName(Long id, String name, EntityManager em, EntityManagerFactory emf) {
EntityTransaction tx = em.getTransaction(); // 트랜잭션 얻음
tx.begin(); // 트랜잭션 시작
try {
Member findMember = em.find(Member.class, id);
findMember.setName(name); // 수정
tx.commit(); // 커밋
} catch (Exception e) {
tx.rollback(); // 롤백
} finally {
em.close(); // DB Connection을 사용하여 작업함
}
emf.close(); // 애플리케이션이 종료되면 닫아야함
}
findMember.setName(name); // 수정
수정이 특이한데 객체의 값을 변경하고 저장(em.persist(findMember);
)하지 않는 다는 점 입니다.
변경 대상(객체
)을 찾고, 대상(객체
)의 값을 변경하면 update
쿼리가 발생합니다.
이를 변경 감지(dirty checking
)이라고 합니다.
더티 체킹이 발생할 수 있는 이유는 바로 em.find(Member.class, id);
을 통해서 조회를 하게 되면 JPA
가 해당 객체를 관리하게 됩니다. 이를 영속성 컨텍스트에 넣는다고 표현 합니다.
영속성 컨텍스트로 관리되는 객체에 변화가 생기면 이를 JPA
가 확인하여 알맞은 쿼리를 생성합니다.
다음시간에는 JPA
에서 가장 중요한 영속성 컨텍스트에 대해서 다뤄보겠습니다.
JPQL
JPA
를 사용하면 엔티티 객체 중심으로 개발이 가능합니다.
문제는 검색 쿼리 인데, 현업에는 조회를 하는데 더 복잡한 쿼리를 사용합니다.
모든 DB 데이터를 객체로 변환해서 검색하는것은 불가능 합니다..😵💫
결국 애플리케이션이 필요한 데이터만 DB에서 불러오려면 검색 조건이 포함된 SQL이 필요합니다.
그래서 등장한 것이 JPQL
입니다.
JPQL
은 SQL
을 추상화한 쿼리 입니다.
테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리입니다.SQL
을 추상화해서 특정 데이터베이스 SQL
에 의존하지 않습니다.
한마디로 JPQL
은 객체 지향 SQL
이라고 말씀드릴수 있겠습니다.
JPQL
에 대한 포스팅은 다음 더 상세히 다루겠습니다.
'0+ 스프링 > 0 + 스프링 ORM(JPA)' 카테고리의 다른 글
[JPA] 연관관계 매핑(@ManyToOne, @OneToMany, @OneToOne, @ManyToMany) (0) | 2023.02.20 |
---|---|
[JPA] 연관관계 매핑 개념(패러다임 불일치 해결) (0) | 2023.02.18 |
[JPA] 엔티티 매핑(@Entity, @Table) (0) | 2023.02.16 |
[JPA] JPA 영속성 컨텍스트(+ flush, 준영속 상태) (0) | 2023.02.09 |
[JPA] JPA 기초 (0) | 2023.02.08 |