데이터를 데이터베이스에 저장하는 3가지 방법
이 중에서 Hibernate는 ORM 프레임워크이고 Mybatis는 SQL Mapper
ORM은 Object Relational Mapping 즉, 객체-관계 매핑의 줄임말이다.
객체-관계 매핑을 풀어서 설명하자면 우리가 OOP(Object Oriented Programming)에서 쓰이는 객체라는 개념을 구현한 클래스와 RDB(Relational DataBase)에서 쓰이는 데이터인 테이블 자동으로 매핑(연결)하는 것을 의미한다. 기술적으로는 어플리케이션의 객체를 RDB 테이블에 자동으로 영속화 해주는 것이라고 보면된다.
그러나 클래스와 테이블은 서로가 기존부터 호환가능성을 두고 만들어진 것이 아니기 때문에 불일치가 발생하는데, 이를 ORM을 통해 객체 간의 관계를 바탕으로 SQL문을 자동으로 생성하여 불일치를 해결한다. 따라서 ORM을 이용하면 따로 SQL문을 짤 필요없이 객체를 통해 간접적으로 데이터베이스를 조작할 수 있게 된다.
Java Persistent API
JPA란 자바 ORM 기술에 대한 API 표준 명세를 의미한다.
JPA는 ORM을 사용하기 위한 인터페이스를 모아둔 것이다. 그 말은 즉, 실제적으로 구현된것이 아니라 구현된 클래스와 매핑을 해주기 위해 사용되는 프레임워크이라는 것. JPA를 사용하기 위해서는 JPA를 구현한 Hibernate, EclipseLink, DataNucleus 같은 ORM 프레임워크를 사용해야한다.
하이버네이트는 기존의 EJB(Enterprise Java Bean) 기술인 엔티티 빈이 가지는 여러 문제들을 대체하기 위한 오픈소스 프레임워크이다. 그리고 ORM을 쉽게 사용하기 위한 ORM 표준이 바로 JPA
JPA는 JDBC 프로그램에서 JDBC API와 같은 개념이다. JDBC 인터페이스를 이용하여 DB 연동 처리 시, 실제 실행 시에는 인터페이스를 구현한 드라이버 객체가 동작한다. 이렇게 인터페이스를 구현한 객체를 사용함으로써 데이터베이스에 대한 종속성이 낮아지고, 추후에 데이터베이스에 종속적인 드라이버만 교체하면 코드를 수정할 필요는 없어지는 것.
JPA 또한 JPA가 제공하는 인터페이스를 이용하여 데이터베이스를 처리하면, 실제로는 JPA를 구현한 구현체가 동작하게 된다.
JPA는 자바 객체를 컬렉션에 저장하고 관리하는 것과 비슷한 개념이다.
하지만 결국 컬렉션에 저장된 객체를 테이블의 row와 매필하기 위해서는 JDBC API를 이용하여 실질적인 연동 작업을 처리하는 절차가 필요하다. JPA는 자바 애플리케이션과 JDBC 사이에 존재하면서 복잡한 JDBC 절차를 대신 처리한다.
요래..
JPA는 데이터베이스 연동에 사용되는 코드뿐만 아니라 SQL까지 제공한다..!!
어노테이션 | 의미 |
---|---|
@Entity | @Entity 가 설정된 클래스를 엔티티라하며, 기본적으로 클래스 이름과 동일한 테이블과 매핑된다. |
@Table | 엔티티 이름과 매핑될 테이블 이름이 다른 경우, name 속성을 사용하여 매핑 |
@Id | 테이블의 기본 키를 매핑한다. 엔티티의 필수 어노테이션 |
@GeneratedValue | @Id 가 선언된 필드에 기본 키 값을 자동 할당 |
엔티티가 작성되면 JPA 어노테이션을 이용하여 테이블과 엔티티 클래스를 매핑해준다.
META-INF 폴더의 persistence.xml -> JPA의 메인 환경설정 파일
JPA는 무조건 해당 파일을 로딩하여 이 파일의 설정대로 동작한다. persistence.xml에는 영속성 유닛이 설정되어 있다.
이 영속성 유닛에 JPA가 연동할 DB에 대한 정보가 들어있다.
persistence.xml 파일은 <persistence>
태그가 루트 엘리먼트이다. 그리고 <persistence>
는 영속성 유닛에 해당하는
<persistence-unit>
엘리먼트를 가짐
영속성 유닛은 연동하려는 데이터베이스당 하나씩 설정한다.
영속성 유닛을 설정하는 애플리케이션에서는 영속성 유닛 설정을 로딩해서 EntityManagerFactory를 생성할 수 있다. 애플리케이션에서 JPA를 이용하기 위해서는 ENtityManager 객체가 필요한데,
EntityManager는 EntityManagerFactory에서부터 얻어낼 수 있다.
영속성 유닛 설정에서 가장 먼저 등록되는 정보는 엔티티 클래스 목록
스프링 프레임워크 또는 J2EE 환경에서 JPA 사용 시 @Entity 어노테이션이 붙은 엔티티들을 자동 스캔해주기 때문에 따로 등록하지 않아도 되지만,
JPA를 단독으로 사용할 경우 엔티티 클래스를 영속성 유닛에 설정해줘야 한다.
JPA 구현체는 persistence.xml에 설정된 데이터소스 설정을 참조하여 특정 데이터베이스와 커넥션을 연결한다.
JPA의 가장 큰 장점 : 데이터베이스 연동에 필요한 SQL 구문을 자동으로 생성하는 것
그러나 데이터베이스마다 동작이 달라서 데이터베이스 변경 시 이전 데이터베이스와의 차이점을 모두 찾아서 수정해야한다. 시러잉
JPA는 특정 데이터베이스에 최적화된 SQL을 작성하는데, 이 때 작성되는 SQL은 Dialect에 따라서 다 다르다~
JPA는 다양한 ORM 프레임워크를 동일한 방법으로 사용하기 위한 인터페이스에 불과하다. 따라서 JPA 사용 시 실질적으로 기능을 제공할 JPA 구현체에 대한 설정이 필수
속성 | 의미 |
---|---|
hibernate.show_sql | 하이버네이트가 생성한 SQL을 콘솔에 출력 |
hibernate.format_sql | 콘솔에 SQL 출력 시 보기 좋게 포매팅 |
hibernate.use_sql_comments | SQL에 포함된 주석도 같이 출력 |
hibernate.hbm2ddl.auto | DDL 구문을 자동으로 실행할지 지정 |
엔티티의 기본 매핑들
@Entity
, @Id
@Entity
@Id
사용@Entity
어노테이션이 추가된 클래스는 해당 클래스 이름에 해당하는 테이블과 자동으로 매핑된다.@Table
엔티티 이름과 테이블 이름이 일치하지 않는 경우 매핑할 테이블 이름을 지정하는데 사용한다. 중요 속성은 아래와 같다.
@Column
엔티티의 변수와 테이블의 칼럼을 매핑할 때 사용한다. 일반적으로 엔티티의 변수 이름과 칼럼 이름이 다를 때 사용
주로 사용되는 속성은 아래와 같다
@Temporal
java.util.Date 타입의 날짜 데이터 매핑 시 사용
@Transient
엔티티 클래스의 변수들은 대부분 테이블의 칼럼과 매핑되는데, 몇몇 변수는 매핑되는 칼럼이 없거나 검색 관련 변수와 같이 임시로 사용되는 변수들은 아예 매핑에서 제외하는 경우가 있다.
@Transient
는 엔티티 클래스 내 특정 변수를 영속 필드에서 제외할 때 사용한다.
테이블과 매핑되는 엔티티는 반드시 PK 칼럼과 매핑될 식별자 필드가 필요하다. (@Id
어노테이션을 이용하여 매핑)
만일 등록 작업 시 식별자 필드에 값이 설정되어 있지 않으면 예외 발생함
식별자 값을 수동 처리할 수도 있으나 자동처리 하는 것이 바람직하다. 식별자를 자동으로 생성하는 전략들을 알아본다.
식별자 필드에 자동으로 증가된 값을 할당 시, 식별자로 사용할 변수에 @GeneratedValue
어노테이션을 설정한다.
@GeneratedValue
의 속성@Data
@Entity
@TableGenerator(name = "BOARD_SEQ_GENERATOR",
table = "ALL_SEQUENCES",
pkColumnValue = "BOARD_SEQ",
allocationSize = 1
)
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator="BOARD_SEQ_GENERATOR")
private Long seq;
private String title;
private String writer;
private String content;
@Temporal(TemporalType.DATE)
private Date createDate;
private Long cnt;
}
@TableGenerator(name = "BOARD_SEQ_GENERATOR",
table = "ALL_SEQUENCES",
pkColumnValue = "BOARD_SEQ",
allocationSize = 1
)
식별자 필드 seq의 @GeneratedValue
속성으로 식별자 생성 전략을 테이블로 지정하고, generator 속성 값으로 앞에서 생성한 BOARD_SEQ_GENERATOR를 참조한다.