[JPA] 설정, 기본 실습
- [ Backend ]/Spring DB, JPA
- 2021. 12. 28.
설정
JPA 실습을 위해서 실습용 DB를 설치하고, 프로젝트의 pom.xml에 라이브러리를 추가해준다.
spring.io사이트에 들어가서 확인해보면 실습을 진행할 스프링부트 2.6.2버전에서는 hibernate 5.6.3.Final을 사용함을 알 수 있다. 여기서 하이버네이트란 JPA의 구현체로, JPA '인터페이스'를 구현한다. JPA는 단순히 hibernate를 추상화한 인터페이스일뿐, JPA자체로만 동작하지 않는다. 따라서 스프링부트와 호환되는 hibernate버전을 의존관계에 추가해주자)
//pom.xml 일부
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.6.3.Final</version> //스프링부트 버전에 맞춘 하이버네이트 버전
</dependency>
...
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.0.204</version> //사용중인 h2DB version
</dependency>
</dependencies>
다음으로 JPA 설정파일을 추가하자. JPA설정파일은 res/META-INF/persistence.xml에 설정파일을 추가하면 된다.
//persistence.xml 일부
<persistence-unit name="hello"> //jpa db 이름
<properties>
//DB 접근정보 (h2 console에서 입력정보)
<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"/>
//db호환(문자, 함수, 페이징 쿼리 등등)을 위한 hibernate전용 옵션
<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"/>
</properties>
...
시작
EntitymanagerFactory emf = Persistence.createEntityManagerFactory("persistenceUnitName"); // 엔티티매니저 팩토리 반환
Entitymanager em = emf.createEntityManager(); //팩토리에서 엔티티매니저 호출
//추가적인 code작성
//application 종료
em.close();
emf.close();
EntitymanagerFactory : 애플리케이션 로딩 시점에 단 하나만 생성
Entitymanager : 트랜잭션 단위(db connection)마다 생성
@Entity : JPA가 관리할 객체
@Id: 데이터베이스 PK mapping
@Entity //JPA에게 관리해야할 테이블임을 인식
public class Member {
@Id
private Long id;
private String name;
//Getter, Setter …
}
-PK(primary key, 기본키)란?
: 테이블 생성시 정의되며, 관계형 DB에서 테이블에서 항목의 주민등록번호라고 생각하면 쉽다. 기본키는 다른 항목과 절대로 중복되어 나타날 수 없는 단일 값을 가지며, 절대로 null값을 가질 수 없다. 테이블을 기본키를 하나까지만 가질 수 있다.
-FK(foreign key, 외래키)란?
: 다른 테이블의 PK를 참조하는 키. 테이블 생성시 정의되며, FK가 정의된 테이블은 자식 테이블이고, 참조되는 미리 생성되어있던 테이블을 부모 테이블이라고 한다. 부모 테이블의 참조되는 칼럼에 존재하는 값만을 입력할 수 있다.
그럼 이제 생성한 객체DTO를 jpa를 이용해서 테이블에 추가시켜보자
//entitymanager에서 트랜잭션 얻어오고 시작
EntityTransaction tx = em.getTransaction();
tx.begin();
//멤버 추가
Member member = new Member();
member.setId(1L);
member.setName("HelloA");
em.persist(member);
tx.commit();
INSERT sql쿼리문 없이도 테이블에 추가되는것을 확인할 수 있다. JPA가 매핑정보만 보고 알아서 테이블에 추가시켜준것이다. 그런데 위의 코드에는 @Entity만 지정해주었을뿐 어떤 테이블명에 저장하라는 정보는 설정해준 적이 없다. 이는 관례상 jpa가 클래스명과 동일한 테이블에 저장해주기 때문이다. 만약 다른 테이블에 저장하기를 원한다면
@Entity
@Table(name = "customname") //customname이라는 테이블에 추가
public class Member {
...
과 같이 @Table을 이용하여 설정을 추가시킬 수 있다.
주의
- 엔티티 매니저 팩토리는 하나만 생성해서 애플리케이션 전체에서 공유
- 엔티티 매니저는 thread간 공유X
- JPA의 모든 데이터 변경은 트랜잭션 안에서만 진행
코드 전문
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);
//조회, 수정
Member findmember = em.find(Member.class, 1L);
findMember.setName("HelloB");
//em.persist(findMember) >>>>>>>>> 필요X(setName메소드만 호출해줘도 쿼리문이 나간다)
//삭제
em.remove(member);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
예외처리구문을 통해서 에러가 발생하면 rollback();을 통해 엔티티매니저를 닫아주는 예외처리문까지 구현할 수 있다.
이제 여기다가 스프링까지 적용시키면 실무에서는 이러한 복잡한 사용없이 em.persist(member);정도의 호출만 필요로 할 것이다.
신기한점은 수정하고 setter메소드만 호출해주고 persist를 해주지 않아도 쿼리문이 나간다는 점이다. 이는 jpa가 commit시점에 상태를 체크하여 자동으로 UPDATE를 해주기 때문이다.
'[ Backend ] > Spring DB, JPA' 카테고리의 다른 글
[JPA] 기본 키 매핑-SEQUENCE 전략, 에러 해결 (0) | 2022.01.02 |
---|---|
[JPA] 엔티티 매핑 (0) | 2021.12.31 |
[JPA] JPA 구조, 특성 (0) | 2021.12.29 |
[JPA] JPQL 예시 (0) | 2021.12.28 |
[JPA] JPA 공부를 시작하며 + JPA, Spring Data JPA, Hibernate (0) | 2021.12.27 |