Java Persistance API로 자바 플랫폼에서 내부 관계형 데이터 관리를 위한 ORM 기술 표준이다. JPA는 인터페이스로 실제 구현을 해야하는데, 오픈소스로 구현한 예로 Hibernate가 있다.
Application과 JDBC API 사이에 위치하여, 개발자는 JPA를 사용만 하면 되고, 실제 데이터에 대한 접근은 JPA가 JDBC API의 SQL을 호출하여 DB에 접근하게 된다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.25'
}
application.property
에 DB연결 및 JPA설정을 작성한다.
# Server Setting
server.address = localhost
server.port = 8080
# DataSource Setting
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
### MySQL URL 설정
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/dbname?characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=dbuser
spring.datasource.password=dbpassword
# JPA Setting
### DDL generation
spring.jpa.hibernate.ddl-auto=update
### @Entity 어노테이션이 붙은 클래스를 찾아서 ddl을 생성하고 실행
spring.jpa.generate-ddl=false
### SQL문을 Log에 출력
spring.jpa.show-sql=true
### DB를 어떤 것을 사용할지 지정
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.properties.hibernate.format_sql=true
# Logging Setting
logging.level.org.hibernate=info
createDatabaseIfNotExist
: 데이터베이스가 존재하지 않으면 자동으로 생성하는 옵션입니다.useUnicode
: 유니코드 사용 여부를 설정합니다.characterEncoding
: 문자열 인코딩 종류를 설정합니다.characterSetResult
: 결과값의 인코딩 종류를 설정합니다.useSSL
: SSL 사용 여부에 대한 설정입니다.ORM중 하나인 JPA의 어노테이션을 활용한 매핑 방식들을 알아본다.
@Entity
속성String
name@Table
속성[type] 속성 | 설명 |
---|---|
String name | 테이블 명 DEFAULT : snake_case의 Entity 명 |
String catalog | 데이터베이스 catalog 매핑 DEFAULT : default catalog |
String schema | 데이터베이스 schema 매핑 DEFAULT : default schema for user |
UniqueConstraint[] uniqueConstraints | DDL 생성 시에 유니크 제약 조건 생성@Column ,@JoinColumn 에 지정된 제약 조건과기본 키 매핑에 수반되는 제약 조건에 추가로 적용 @Table(uniqueConstraints = {@UniqueConstraint(name = "CONSTRAINT_NAME", columnNames = {"name", "phone"})}) DEFAULT : no additional constraint |
Index[] index | 테이블의 인덱스 기본 키의 인덱스는 자동으로 생성됨 |
JPA/Hibernate Naming 전략
순서
1. 도메인 모델 매핑으로부터 적절한 논리적 이름을 정한다.
1-1. 논리적 이름은 @Column 또는 @Table등을 사용해서 사용자로 부터 이름을 부여 받거나 ImplicitNamingStrategy 전략을 통해서 Hibernate를 통해 암묵적으로 부여 받는다.
2. PhysicalNamingStrategy 전략을 통해서 논리적 이름을 물리적 이름으로 정의하는 것이다. (camelCase --> snake_case)ImplicitNamingStrategy
@Column
,@Table
의 name 속성으로 지정한 이름으로 매핑attributeName
속성 이름이 별도 지정하지 않은 경우 "attributeName"으로 매핑- application.properties 설정
- spring.jpa.hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
PhysicalNamingStrategy
- 특별하게 column name을 명시하였거나 암묵적으로 결정 되었는지에 관련 없이 적용
- attr_name 처럼 별도 물리적 컬럼 이름으로 대신하게 할 수 있다.
- application.properties 설정
- spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
변수 이름 그대로 사용
- spring.jpa.hibernate.naming.physical-strategy = org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
[type] 속성 | 설명 |
---|---|
String name | 컬럼 명 지정 DEFAULT : camelCase의 필드명 (application.properties에 전략을 번경해주면 snake_case 형태로 바꿀 수 있다.) |
boolean unique | Unique 속성 지정 DEFAULT : False |
boolean nullable | NULLABLE 속성 지정 DEFAULT : True |
boolean insertable | JPA에 의해 만들어진 INSERT 명령에 포함되는지 지정 DEFAULT : True |
boolean updatable | JPA에 의해 만들어진 UPDATE 명령에 포함되는지 지정 DEFAULT : True |
String columnDefinition | Column에 대한 DDL 생성 @Column(columnDefinition = "varchar(100) default 'EMPTY'") DEFAULT : If absent the column is assumed to be in the primary table |
String table | 해당 Column을 포함하는 테이블 이름 |
int length | String 타입의 컬럼에 길이 제한 지정 DEFAULT : 255 |
int precision | 10진수 숫자의 값을 가지는 열에 대한 전체 자리수 DEFAULT : 0 |
int scale | 10진수 숫자의 소수점 이후 자리수 DEFAULT : 0 |
@Id
어노테이션이 붙은 Primary Key에 대해 MySQL의 Auto Increment 특성을 걸어준다.@SequenceGenerator
어노테이션과 같이 이용한다.@Embeddable
public class TestKey implements Serializable {
@Column(name = "first_key"
private Long firstKey
@Column(name = "second_key"
private Long secondKey
}
@Entity
public class EmbeddableTest {
@EmbeddedId
protected TestKey testKey;
}
enum TestTF {
False, True
}
@Enumerated(EnumType.ORIDNAL)
@Column(name="ordinal_tf")
private TestTF ordinalTF; // 0, 1로 저장
@Enumerated(EnumType.STRING)
@Column(name="string_tf")
private TestTF stringTF; // "False", "True"로 저장
@Id
가 필드에 있으면 기본적으로 필드 접근 방식을 사용한다.@Entity
public class Member {
@Id
private String id;
@Transient
private String firstName;
@Transient
private String lastName;
@Access(AccessType.PROPERTY)
public String getFullName(){
return this.firstName + this.lastName;
}
}