안녕하세요. 개발자 Jindory입니다.
오늘은 JPA 기초에 대해서 알아보는 글을 작성해보고자 합니다.
JPA 기초
JPA 기초를 실습을 통해 알아보도록 하겠습니다.
- 개발환경
- Java Eclipse 2021.12
- Java 8버전
- Maven
- 라이브러리
- hibernate-entitymanager 5.3.7.Final
- com.h2database 1.4.197
- jaxb-api 2.3.0
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>hellojpa</groupId> <artifactId>hellojpa</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>5.3.7.Final</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.197</version> </dependency> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency> </dependencies> </project>
JPA 설정
JPA을 설정을 위해 src\main\resources\META-INF\persistence.xml에 아래와 같이 설정을 해줍니다.
아래의 설정은 H2 Database와 연결한다는 전제하에 설정한 것으로, Mysql이나 Oracle 외 다른 Database를 사용시 value값이 달라진다.
[persistence.xml]
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.2">
<persistence-unit name ="hello">
<properties>
<!-- 필수 속성 -->
<!-- jdbc driver를 h2 dirver로 설정 -->
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<!-- jdbc user를 sa로 설정(H2 databse 기본설정 -->
<property name="javax.persistence.jdbc.user" value="sa"/>
<!-- jdbc 비밀번호 설정 -->
<property name="javax.persistence.jdbc.password" value=""/>
<!-- 연결할 jdbc url을 설정-->
<property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test"/>
<!-- jpa에서 반환할 SQL을 H2 database로 설정 -->
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<!-- 옵션 -->
<!-- SQL문이 console에 보이도록 설정 -->
<property name="hibernate.show_sql" value="true"/>
<!-- SQL format이 정리되어 나오도록 설정 -->
<property name="hibernate.format_sql" value="true"/>
<!-- SQL에 주석 허용 -->
<property name="hibernate.use_sql_comments" value="true"/>
<!--property name="hibernate.hbm2ddl.auto" value="create"/-->
</properties>
</persistence-unit>
</persistence>
위에 설정에 보면 hibernate.dialect 설정을 하는데, Mysql, Oracle, Postgre 등등 SQL 마다 문법이 다르므로 데이터베이스 마다 변경해줄 필요가 있다. JPA는 특정 데이터베이스에 종속적이지 않으므로 dialect를 설정하므로써 설정한 데이터베이스의 SQL문을 생성해준다.(여기에서 각 SQL에 따른 설정을 확인 할 수 있다)
JPA Entity 설정
객체의 정보를 저장하고 JPA로 넘길 객체를 Member를 아래와 같이 생성한다.
@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 void String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
- @Entity
- 테이블과 매핑
- @Entity가 붙은 클래스는 JPA가 관리하는 것으로, 엔티티라고 불림
- Name 속성으로 지정하지 않으면 class 이름을 보통 Table명과 매핑시킴.
엔티티 매니저 설정
META-INF/persistence.xml에 설정한 값을 조회한 후 persistence에서 설정한 값을 Persistence.createEntityManagerFactory("hello")값을 통해 생성하여 EntityManagerFactory를 만든다.
여기서 hello는 persistence.xml에서 persistence-unit name에서 설정한 이름을 넣어주어야 한다.
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(100L);
member.setName("홍길동");
em.persist(member);
tx.commit();
}catch(Exception e ) {
tx.rollback();
}finally{
em.close();
}
emf.close();
}
- EntityManager를 생성한 후 EntityTransaction을 생성해야하는데, 그 이유는 JPA는 하나의 Transaction 안에서 이루어져야 하기 때문에, Transaction을 먼저 설정한다.
transaction은 tx.begin();으로 시작해서 tx.commit();과 동시에 종료된다.
먼저 Member 객체를 생성한 후 값을 셋팅하고 EntityManager에 persist로 객체를 전달하면 Database에 값이 저장되는것을 확인 할 수 있다.
데이터베이스 스키마 자동 생성
- 어플리케이션 실행 시점에 DDL을 자동으로 생성이 가능하다.
- 테이블 중심이 아닌 객체 중심의 테이블을 생성한다.
- 데이터베이스 방언을 활용하여 데이터베이스에 맞는 DDL을 생성한다.
- 스키마 자동생성 옵션
- create : 기존 테이블 삭제 후 다시 생성(DROP + CREATE)
- create-drop : create와 같으나 종료시점에 테이블을 DROP
- update : 변경분만 반영(운영DB에서는 사용하면 안 됨)
- validate : 엔티티와 테이블이 정상 매핑되었는지만 확인
- none : 사용하지 않음.
매핑 어노테이션
객체의 값을 테이블과 매핑해주기 위해 선언하는 어노테이션들이다.
@Entity
public class Member {
@Id
private Long id;
@Colun(name="USERNAME")
private String name;
private int age;
@Temporal(TemporalType.TIMESTAMP)
private Date regDate;
@Enumerated(EnumType.STRING)
private MemberType memberType;
}
- @Id
- 영속성 컨텍스트는 엔티티를 식별자 값으로 구분하므로 엔티티를 영속 상태로 만들기 위해 식별가 값이 반드시 필요하다.
- 기본키 생성 전략
- 직접 할당 : 기본 키를 어플리케이션에 직접 할당
em.persis()를 호출하기 전 어플리케이션에서 직접 실별자 값을 할당해야함. 식별자 값이 없을 경우 에러 발생 - 자동 생성 : 대리키 사용 방식
- IDENTITY : 기본 키 생성을 데이터베이스에 위임(=AUTO_INCREMEMT)
- SEQUENCE
- 데이터베이스 시퀀스를 사용해서 기본키를 할당한다
- 데이터베이스 시퀀스에서 식별자 값을 획득한 후 영속성 컨텍스트에 저장한다.
- 유일한 값을 순서대로 생성한다(Oracle, PostgreSQL, DB2, H2)
- Table
- 키 생성 테이블을 사용
- 키 생성 전용 테이블 하나를 만들고 여기에 이름과 값으로 사용할 칼럼을 만들어 데이터베이스 시퀀스를 흉내내는 전략이다.
- 테이블을 사용하므로 모든 데이터베이스에 적용 가능하다.
- AUTO
- 선택한 데이터베이스 방언에 따라 방식을 자동으로 선택한다.
Ex) Oracle DB 선택시 SEQUENCE, MySQL DB 선택 시 IDENTITY 사용
- 선택한 데이터베이스 방언에 따라 방식을 자동으로 선택한다.
- 직접 할당 : 기본 키를 어플리케이션에 직접 할당
- @Column
- 객체 필드를 테이블 컬럼에 매핑할때 사용한다.
- 속정 중 name, nullable이 주로 사용되고 나머지는 잘 사용되지 않는다.
- 속성
- name : 필드와 매핑할 테이블 칼럼의 이름(default, 객체의 필드 이름)
- nullable(DDL) : null 값의 허용 여부 설정, false 설정시 not null(default true)
- unique(DDL) : @Table의 uniqueContranints와 같지만 한 칼럼에 간단히 유니크 제약조건을 적용
- columnDefinition(DDL) : 데이터베이스 컬럼 정보를 직접 줄 수 있음, defalut 값 설정
- length(DDL) : 문자 길이 제약조건, String 타입에만 사용(default 255)
- percision,scale(DDL) : BigDecimal, BigInteger 타입에서 사용. 아주 큰 숫자나 정밀한 소수를 다룰 때만 사용(default precision = 19, scale = 2)
- @Temporal
- 날짜 타입(java.utilDate, java.util.Calendar)을 매핑할 때 사용
- 속성
- value
- TemporalType.DATE : 날짜, 데이터베이스 date 타입과 매핑(2022-02-16)
- TemporalType.Time : 시간, 데이터베이스 time 타입과 매핑(22:20:25)
- TemporalType.TIMESTAMP : 날짜와 시간, 데이터베이스 timestamp 타입과 매핑(2022-02-16 22:20:25)
- value
- @Temporal을 생랼하면 자바의 Date와 가장 유사한 timestamp로 정의
- @Enumerated
- 자바의 enum 타입을 매핑할 때 사용
- 속성
- value
- EnumType.ORDINAL : enum 순서를 데이터베이스에 저장
- EnumType.STRING : enum 이름을 데이터베이스에 저장
(default EnumType.ORDINAL)
- value
- @Lob
- 데이터베이스 BLOB, CLOB 타입과 매핑
- 속성
- 지정 속성 없음
- 대신 매핑하는 필드 타입이 문자면 CLOB으로 나머지는 BLOB으로 매핑
- @Transient
- 이 필드는 데이터베이스에 매핑하지 않음
- 데이터페이스에 저장하지 않고 조회도 하지 않음
- 객체에 임시로 어떤 값을 보관하고 싶을 때 사용
이렇게 JPA 기초에 대해서 알아봤습니다.
혹시라도 정정할 내용이나 추가적으로 필요하신 정보가 있다면 댓글 남겨주시면 감사하겠습니다.
오늘도 Jindory 블로그에 방문해주셔서 감사합니다.
[ 참조 ]
https://www.youtube.com/watch?v=egVZusxSeKw&list=PL9mhQYIlKEhfpMVndI23RwWTL9-VL-B7U&index=2
https://www.youtube.com/watch?v=TYO42hpPLq4&list=PL9mhQYIlKEhfpMVndI23RwWTL9-VL-B7U&index=3
https://data-make.tistory.com/610
'개발 > JPA' 카테고리의 다른 글
[JPA] JPA 관련 application.properties 설정 (0) | 2022.04.27 |
---|---|
[JPA] 객체지향 쿼리 (0) | 2022.02.22 |
[JPA] JPA 영속성 컨텍스트 (0) | 2022.02.22 |
[JPA] JPA 연관관계 매핑 (0) | 2022.02.17 |
[JPA] JPA란 무엇일까? (0) | 2022.02.16 |