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

이정수·2025년 11월 7일

Spring JPA

목록 보기
5/9

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을 자동생성

  • @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에 선언

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

@GeneratedValue(strategy = GenerationType.정책) : jakarta.persistence
。주로 @Id가 선언된 PK 역할의 Field에 함께 선언하여 JPA에 의해 Entity영속화 시점에서 중복이 없는 을 자동할당하여 개체무결성 보장

Entity영속성 컨텍스트에 등록하여 영속화JPA에 의해 설정된 Strategy에 따라 중복이 없는 PK값을 자동생성

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

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

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

    GenerationType.AUTO : JPADB Dialect에 따라 적절한 Strategy ( IDENTITY, SEQUENCE 등 )을 선택

    GenerationType.UUID : UUID Type 식별자를 자동으로 생성 및 설정
    @Id FieldData typejava.util.UUID로 설정되어야 한다.
@Id
@GeneratedValue(strategy= GenerationType.UUID)
private UUID id;

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

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

  • @Column(nullable = false)
    DB TableNOT NULL 제약조건을 추가

@Transactional : org.springframework.transaction.annotation
DB트랜잭션을 수행할때 원자성을 보장하기 위해 경계를 설정하여 commit / rollback을 자동으로 관리하는 기능이 추상화어노테이션
호출이 정상종료 시 commit, 예외 발생 시 rollback하여 원자성을 보장

Spring BeanService Class내에서 사용되므로 jakarta가 아닌 Spring@Transactional을 사용

PSA를 기반으로 구현된 어노테이션으로서 어떤 DB( PostgreSQL, MySQL )를 사용하던 상관없이 동일한 사용법동일한 DB Transaction을 보장

Production Code가 아닌 Test Code에서 테스트 클래스클래스 레벨에 선언하는 경우 Test가 끝난경우 자동으로 DB를 다시 Transaction 수행 이전으로 Rollback
▶ 이때 클래스명 뒤에 Test 키워드가 붙어야한다. ( ex. UserTest.java )

Service Class에서 JpaRepository에 의해 Entity를 통한 CRUD가 구현된 메서드 레벨에서 선언
클래스 레벨에서 선언하여 Service Class내 모든 메서드@Transactional을 일괄적으로 적용 가능

  • @Transactional(readOnly = true) :
    쓰기를 금지하고 읽기만 가능
    @Transactional(readOnly=true)를 선언할 경우 Dirty Checking이 차단되어 Entity수정되더라도 DB Table에 반영되지않음

    。주로 findById() 또는 List 조회 등 조회 목적의 메서드에 선언

  • @Transactional(propagation = Propagation.REQUIRES_NEW)
    。복수의 트랜잭션호출관계에 따라서 기존 트랜잭션을 그대로 이어서 할건지, 새로 트랜잭션을 생성할지를 결정

    REQUIRES_NEW : 항상 새 트랜잭션을 생성하며 기존 트랜잭션이 존재하는 경우 일시중단
    트랜잭션독립을 보장

    @Transactional 원리

    private final PlatformTransactionManager transactionManager;
    	public void createMember(MemberCreateRequest request){
    		var transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());
    		try{
    			var member = new MemberEntity(
    				//
    			);
    			memberRepository.save(member);
    		}catch(Exception e){
    			// 실패 시 롤백
    			transactionManager.rollback(transaction);
    		}
    		// 커밋
    		transactionManager.commit(transaction);
    	}

    DBTransaction을 수행 시 원자성을 보장하기위해 transactionManager를 통한 commitrollback을 수행하는 코드를 일일히 지정

    @Transactional // 트랜잭션의 원자성 보장
    	public void createMember(MemberCreateRequest request){
    		var member = new MemberEntity(
    			//
    		);
    		memberRepository.save(member);
    	}

    ▶ 해당 과정을 단순하게 메서드 레벨에서 @Transactional을 선언하여 원자성을 보장가능

@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에 저장하는 방식으로 기본설정되어있으나 절대 사용 x

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

@EnableAsync :
@Async가 선언된 메서드비동기로 실행할 수 있도록 선언하는 어노테이션

@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개의 댓글