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로 등록 시 선언하는어노테이션
▶VO를DB Table와 Mapping하는DB Entity선언
。@Entity는Spring의@Component를 포함하지않으므로 선언된클래스는Spring Bean이 될 수 없음
。new를 통해 생성 직후의DB Entity 객체는비영속이므로DB Table과Mapping되지 않은 상태.
▶EntityManager.save(Entity)를 통해영속성 컨텍스트에 등록해야DB Table에Mapping되어DB Entity를 통한CRUD를 수행
▶ 생성된DB Entity에 Data를 삽입 및 수정하여영속성 컨텍스트에 등록 시매핑된DB Table에 자동으로 반영
。@Entity를 선언한클래스는 반드시기본 생성자와@Id를 선언한PK를 포함
。ddl-auto: update를 설정한 경우Auto Configuration에 의해@Entity가 선언된POJO를 식별시DB에Entity의 속성을구현 및 매핑한DB Table을 자동생성
@Entity(name="별칭명")
。JPA에 의해 인식하는Entity명을자바클래스명이 아닌 다른별칭으로 명시적으로 설정 시 사용하는 속성
。JPA에게 인식되는명칭을 설정하므로Entity Class와Mapping할DB Table을 명시적으로 설정하는것과 유사하나 이 목적으로 사용 시 실제DB Table명과매핑하는@Table(name="테이블명")을 선언하는것을 권고.
@Table(name="DBtable이름")
。@Entity Class에 선언하여DB Entity가Mapping할 실제DB Table명을 명시적으로 설정
▶DB Table명칭이JavaClass명과 다른 경우 주로 사용
@Id:jakarta.persistence
。DB Entity Class에서DB Table에서의PK로 정의할Field에 선언
▶ 주로@GeneratedValue와 함께Entity Class의Field에 선언
。Auto Configuration에 의한DB Table자동 생성 시 해당Field가PK의Column으로 자동설정
@GeneratedValue(strategy = GenerationType.정책):jakarta.persistence
。주로@Id가 선언된PK역할의Field에 함께 선언하여JPA에 의해Entity의영속화시점에서중복이 없는값을 자동할당하여개체무결성보장
。Entity를영속성 컨텍스트에 등록하여영속화시JPA에 의해 설정된Strategy에 따라 중복이 없는PK값을 자동생성
。@Id가 선언된Field는@GeneratedValue에 의해영속화 시점에서 자동할당되므로 향후Entity 객체생성 시매개변수에null로 설정하여 생성.
Strategy종류
。@Id Field에 대해 다음 전략들을 설정
。GenerationType.IDENTITY:DB의AUTO-INCREMENT기능 사용
▶ 데이터INSERT시점에서PK값이 생성
。GenerationType.AUTO:JPA의DB Dialect에 따라 적절한Strategy(IDENTITY,SEQUENCE등 )을 선택
。GenerationType.UUID:UUID Type 식별자를 자동으로 생성 및 설정
▶@Id Field의Data type은java.util.UUID로 설정되어야 한다.@Id @GeneratedValue(strategy= GenerationType.UUID) private UUID id;
@Column("DBtableColumn명"):
。@Entity Class의Field에 선언하여DB Table의 특정Column과Mapping
▶ 만약Class의Field명과mapping할DB Table의Coulmn명이 동일한 경우, 따로 선언하지않아도된다.
。Auto Configuration에 의한DB Table자동 생성 시@Column("설정될Coulumn이름")이 선언된 경우 해당Column명으로DB Table을 생성
@Column(nullable = false)
。DB Table에NOT NULL 제약조건을 추가
@Transactional:org.springframework.transaction.annotation
。DB에트랜잭션을 수행할때원자성을 보장하기 위해경계를 설정하여commit / rollback을 자동으로 관리하는 기능이추상화된어노테이션
▶호출이 정상종료 시commit,예외발생 시rollback하여원자성을 보장
。Spring Bean인Service 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); }。
DB에Transaction을 수행 시원자성을 보장하기위해transactionManager를 통한commit과rollback을 수행하는코드를 일일히 지정@Transactional // 트랜잭션의 원자성 보장 public void createMember(MemberCreateRequest request){ var member = new MemberEntity( // ); memberRepository.save(member); }▶ 해당 과정을 단순하게
메서드 레벨에서@Transactional을 선언하여원자성을 보장가능
@Enumerated(EnumType.STRING):jakarta.persistence.Enumerated
。@Entity Class내Enum type의필드에 선언하여Enum을DB에 저장하기위해 선언하는어노테이션
▶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명")
。부모 Entity의PK를연관관계를 통해자식 Entity에서외래키로 참조 시 해당외래키 필드에 선언하여자식 Entity의PK로매핑하는어노테이션
▶외래키를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개의
컬럼이 동기화가 되지않고 서로 다른컬럼으로서 생성됨