JPA - @Entity, @Table, @Id, @GeneratedValue, @Column , @Enumerated, @EnableAsync , @Async , @MapsId

TopOfTheHead·2025년 11월 7일

Spring JPA

목록 보기
4/10

JPA ( jakarta.persistence )에 속한 어노테이션
@Entity, @Table, @Id, @GeneratedValue, @Column, @Enumerated, @MappedSuperclass
Spring과 관련이 없으므로 @Entity를 선언하더라도 Spring Bean으로 등록되지 않는다.


Spring에 속한 어노테이션
@Transactional , @Query
Spring Bean@Service Class 내에서 활용되므로 다음 어노테이션을 사용

@Entity : jakarta.persistence
JPA에서 자바 클래스( = VO )를 DB Entity로 등록 시 선언하는 어노테이션
VODB Table와 Mapping하는 DB Entity 선언

@EntitySpring@Component를 포함하지않으므로 선언된 클래스Spring Bean이 될 수 없음

new를 통해 생성 직후의 DB Entity 객체비영속이므로 DB TableMapping되지 않은 상태.
EntityManager.save(Entity)를 통해 영속성 컨텍스트에 등록해야 DB TableMapping되어 DB Entity를 통한 CRUD를 수행
▶ 생성된 DB Entity에 Data를 삽입 및 수정하여 영속성 컨텍스트에 등록 시 매핑DB Table에 자동으로 반영

@Entity를 선언한 클래스는 반드시 기본 생성자@Id를 선언한 PK를 포함

ddl-auto: update를 설정한 경우 Auto Configuration에 의해 @Entity가 선언된 POJO를 식별시 DBEntity의 속성을 구현 및 매핑DB Table을 자동생성

Hibernate의 경우 내부적으로 Lazy Loading을 통한 프록시 객체를 사용하므로, @Entity 클래스 선언 시 final이 선언이 불가능
final 키워드로 인해 CGLIB동적프록시 객체 생성이 봉쇄되므로.

  • @Entity(name="별칭명")
    JPA에 의해 인식하는 Entity명자바클래스명이 아닌 다른 별칭으로 명시적으로 설정 시 사용하는 속성

    JPA에게 인식되는 명칭을 설정하므로 Entity ClassMappingDB Table을 명시적으로 설정하는것과 유사하나 이 목적으로 사용 시 실제 DB Table명매핑하는 @Table(name="테이블명")을 선언하는것을 권고.

@Table(name="DBtable이름")
@Entity Class에 선언하여 DB EntityMapping할 실제 DB Table명을 명시적으로 설정
DB Table 명칭이 JavaClass명과 다른 경우 주로 사용

@Id : jakarta.persistence
DB Entity Class에서 DB Table에서의 PK로 정의할 Field에 선언
주로 @GeneratedValue와 함께 Entity ClassField에 선언

@Id 필드의 경우 반드시 참조형 변수로 선언
NPE 방지

Auto Configuration에 의한 DB Table 자동 생성 시 해당 FieldPKColumn으로 자동설정

@GeneratedValue(strategy = GenerationType.정책, generator = "인덱스생성자명ㅈ") : jakarta.persistence
。주로 @Id가 선언된 PK 역할의 Field에 함께 선언하여 DBAUTO INCREMENT 기능을 사용하도록 설정하는 어노테이션

@Id가 선언된 Field@GeneratedValue에 의해 Entity 영속화 시점에서 PK값자동 할당되므로 향후 Entity 객체 생성 시 매개변수null로 설정하여 생성.


Strategy 종류
@Id Field에 대해 다음 전략들을 설정

  • GenerationType.IDENTITY :
    DBAUTO-INCREMENT 기능 사용
    ▶ 데이터 INSERT 시점에서 PK값이 생성

  • GenerationType.SEQUENCE
    EntityINSERT 이전에 DB에서 PK값을 가져온 후 할당
    PostgreSQL , Oracle에서 지원

    @SequenceGenerator 어노테이션을 활용하여 SEQUENCE를 지원하지 않는 DBMS ( = MySQL )에도 적용 가능
    initialValue 속성allocationSize 속성을 통해 인덱스의 증가량을 정의
@Entity
@SequenceGenerator(
	name = "SAMPLE_SEQ_GENERATOR",
	initialValue = 1,
	allocationSize = 1
) 
public class SequenceMapping {
	@Id
	@GeneratedValue(
		strategy = GenerationType.SEQUENCE,
		generator = "SAMPLE_SEQ_GENERATOR" // SEQUENCE 사용 시 @SequenceGenerator을 적용하여 사용해야한다.
	)
	private Long id;
}
  • GenerationType.TABLE
    。별도의 PK 관리 용도테이블을 생성하여 PK를 관리

    DBMS에 독립적으로 작용하므로, 어느 DBMS에서든 사용 가능
    ▶ 단, 성능이 매우 안좋은 단점이 존재
@Entity
@TableGenerator(
	name = "SAMPLE_SEQ_TABLE_GENERATOR",
	table = "SAMPLE_SEQUENCE_CHECK",	// 해당 Generator의 Table이 DB에서 생성
	pkColumnName = "SAMPLE_ACCOUNT_SEQ", // 생성될 테이블의 PK명 지정
	allocationSize = 1
)
public class TableGenerationMapping {
	@Id
	@GeneratedValue(
		strategy = GenerationType.TABLE,
		generator = "SAMPLE_SEQ_TABLE_GENERATOR"
	)
  • GenerationType.AUTO :
    DB Dialect에 따라 적절한 Strategy ( IDENTITY, SEQUENCE 등 )을 선택
    @GeneratedValue의 기본값은 AUTO

  • GenerationType.UUID :
    UUID Type 식별자를 자동으로 생성 및 설정
    @Id FieldData typejava.util.UUID로 설정되어야 한다.

    PK 길이가 매우 길고, 인덱스 성능이 매우 안좋은 단점이 존재
    분산 시스템에서 주로 활용
@Id
@GeneratedValue(strategy= GenerationType.UUID)
private UUID id;

@Column("DBtableColumn명") :
@Entity ClassField에 선언하여 DB Table의 특정 ColumnMapping
▶ 만약 ClassField명mappingDB TableCoulmn명이 동일한 경우, 따로 선언하지않아도된다.

ddl-auto에 의한 Hibernate에 의해 DB Table 자동 생성 시 @Column("설정될Coulumn이름")이 선언된 경우 해당 Column명으로 DB Table을 생성

  • @Column(nullable = false)
    。해당 필드에 해당하는 컬럼NOT NULL 제약조건을 추가
    nullable = falseHibernate에게 ddl-auto 생성 시 해당 필드제약조건 : not null로 설정하는 속성으로 Entity에 입력되는 데이터 자체를 검사해주지는 않는다.

  • @Column(length = 1~255)
    。해당 필드에 해당하는 문자열 컬럼( CHAR / VARCHAR )에 길이 제약조건 지정
    비밀번호 필드평문으로 설정하면 안되므로 매우 길게 설정.

  • @Column(columnDefinition = "자료형 DEFAULT 숫자")
    。해당 필드에 해당하는 컬럼NULL값이 입력된 경우 기본값을 지정하도록 제약조건 설정
    ex ) INT DEFAULT 0 , TEXT

  • @Column(unique = true)
    。해당 필드unique 제약조건을 설정

@Enumerated(EnumType.STRING) : jakarta.persistence.Enumerated
@Entity ClassEnum type필드에 선언하여 EnumDB에 저장하기위해 선언하는 어노테이션
Enum의 값을 String으로서 DB에 저장

JPA는 기본적으로 @Enumerated(EnumType.ORDINAL)Enum값이 아닌 Enum인덱스DB에 값을 넣으므로 @Enumerated(EnumType.STRING)를 따로 선언해야함

@Enumerated(EnumType.STRING)
	private Gender gender; 
  • @Enumerated(EnumType.ORDINAL)
    ordinal : enum인덱스DB에 저장하는 방식으로 기본설정되어있으나 사용하지 않는다.
    Enum Class 수정 시 데이터 순서가 임의로 변경될 수 있으므로 사용하지 않는 것을 권고

@Async :
。선언한 메서드를 별도의 ThreadPool스레드에서 비동기로 실행하는 어노테이션

@EnableAsync진입점 클래스에 선언해야 비동기 사용 가능.
▶ 선언하지 않으면 동기로 작동

。선언된 메서드와 동일한 클래스 내에서 호출 시 기능하지 않는다.
Spring Proxy를 이용하지 않으므로

@Async
public void asyncMethod() {
    System.out.println("비동기 실행");
}

▶ 해당 메서드 호출 시 다른 스레드에서 해당 메서드를 처리

@EnableAsync :
@Async가 선언된 메서드비동기로 실행할 수 있도록 선언하는 어노테이션
▶ 보통 @SpringBootApplication이 선언된 진입점 클래스에 선언

@MapsId("부모Entity PK명")
부모 EntityPK연관관계를 통해 자식 Entity에서 외래키로 참조 시 해당 외래키 필드에 선언하여 자식 EntityPK매핑하는 어노테이션
외래키PK로 사용되도록 매핑을 수행

  • @MapsId를 활용해 부모 테이블을 참조하는 외래키기본키로 하는 식별관계테이블 정의
    。생성되는 accountId 컬럼PK 이자 FK로서 생성
@Entity
@Table(name = "accountnetwork")
public class AccountNetwork{
	@Id
	@Column(name = "account_id")
	private UUID accountId;
	@MapsId("id")
	@OneToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "account_id")
	private Account account;
}
create table accountnetwork (
	account_id UUID not null,
	primary key(account_id),
	foreign key(account_id) references account(id)
);

▶ 다음처럼 PK속성과 동시에 FK속성을 지닌 DB Table이 생성

@MapsId를 사용하지 않는 경우

@Entity
class UserProfile {
    @Id
    private Long id;
    @OneToOne
    @JoinColumn(name = "user_id")
    private User user;
}

▶ 2개의 컬럼이 동기화가 되지않고 서로 다른 컬럼으로서 생성됨

profile
공부기록 블로그

0개의 댓글