개발/JPA

[JPA] JPA 기초

Jindory 2022. 2. 16. 22:49
반응형

안녕하세요. 개발자 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>

H2 Database 설정정보

위에 설정에 보면 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)
    • @Temporal을 생랼하면 자바의 Date와 가장 유사한 timestamp로 정의
  • @Enumerated
    • 자바의 enum 타입을 매핑할 때 사용
    • 속성
      • value
        • EnumType.ORDINAL : enum 순서를 데이터베이스에 저장
        • EnumType.STRING : enum 이름을 데이터베이스에 저장
          (default EnumType.ORDINAL)
  • @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

 

반응형