[UMC] 5주차. JPA 기초 및 프로젝트 구조

yoons(이윤서)·2024년 10월 30일

[Server] UMC workbook

목록 보기
2/2

어노테이션 정리


domain 패키지
-> Member.java

@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
}
  • 기본키를 만들 때 사용한 어노테이션
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    : JPA가 통신을 하는 DBMS의 방식을 따른다

  • @Entity : 어노테이션을 통해 해당 클래스가 JPA의 엔티티임을 명시
    @Getter : lombok 제공. getter을 만들어주는 어노테이션

  • @Builder
    @NoArgsConstructor(access = AccessLevel.PROTECTED)
    @AllArgsConstructor
    : 위 세 개의 어노테이션은 자바의 디자인 패턴 중 하나인 빌더 패턴을 사용하기 위함. 빌더 패턴을 사용하면 생성자를 사용하는 것보다 더욱 편리하게 코당 가능.


[ 빌더 패턴 관련 참고자료 ]
https://mangkyu.tistory.com/163
https://readystory.tistory.com/121
https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EB%B9%8C%EB%8D%94Builder-%ED%8C%A8%ED%84%B4-%EB%81%9D%ED%8C%90%EC%99%95-%EC%A0%95%EB%A6%AC



@Getter, @Setter


[참고자료]: [OOP] Getter와 Setter는 지양하는게 좋다 by 개발하는 곰돌이
https://colabear754.tistory.com/173

@Getter@Setter의 사용 지양할 것.

  • Setter 대신 명확한 의도를 가진 메소드를 사용하라.
  • Getter로 조건을 검사하지 말고 결과를 반환하게 하라.
  • Ex) 출금의 경우,
    AccountService에서 계좌 잔액 충분한지 확인 -> 잔액 변경 (X)
    그냥 Account에 출금할 금액을 전달 -> 출금 (O)
class Account {
 	private long balance;
    
    public void withdraw(long amount) {
        if (amount > balance) {
            throw new IllegalArgumentException("잔액이 부족합니다.");
        }       
        balance -= amount;
    }
}

@Service
public class AccountService {
   	...    
    public void withdraw(long id, long amount) {
       	Account account = accountRepository.findById(id).orElseThrow();
       	account.withdraw(amount);
    }
    ...
}

= 이렇게 하면 코드가 간결해짐과 동시에 의도도 명확해졌다.



@Enumerated


정해진 값들 중에서 특정 값이 저장되는 경우,
Ex) gender, status, social_type
String 타입을 사용하기 보다는 enum을 사용하는 것이 좋다.

이때 EnumType은 반드시 STRING !!

ORDINAL 사용시 데이터베이스에 enum의 순서가 저장되는데,
만약 enum의 순서를 바꿀 경우 에러가 생김.

Created_at, Updated_at


@EnableJpaAuditing

JPA Auditing(감시,감사)

데이터베이스에서 누가, 언제 하였는지 기록을 잘 남겨놓아야 합니다.
때문에 생성일, 수정일 컬럼이 대단히 중요합니다.
JPA에서 제공하는 기능인 Audit은 Spring Data JPA에서 시간에 대해서 자동으로 값을 넣어주는 기능입니다.

  1. build.gradle
    spring-boot-starter-data-jpa만 추가해도 Audit을 하는데는 문제가 없습니다.
  2. BaseTimeEntity.java
@Getter
@MappedSuperclass 
@EntityListeners(AuditingEntityListener.class) 
public abstract class BaseTimeEntity{

    // Entity가 생성되어 저장될 때 시간이 자동 저장됩니다.
    @CreatedDate
    private LocalDateTime createdDate;

    // 조회한 Entity 값을 변경할 때 시간이 자동 저장됩니다.
    @LastModifiedDate
    private LocalDateTime modifiedDate;

}
  1. Spring boot Application에 @EnableJpaAuditing추가
@SpringBootApplication
@EnableJpaAuditing
public class StudyApplication {

	public static void main(String[] args) {
		SpringApplication.run(StudyApplication.class, args);
	}

}

@MappedSuperclass

JPA Entity 클래스들이 해당 추상 클래스를 상속할 경우 createDate, modifiedDate를 컬럼으로 인식

@EntityListeners(AuditingEntityListener.class)

해당 클래스에 Auditing 기능을 포함

@CreatedDate/@LastModifiedDate

Entity가 생성되어 저장될 때 시간이 자동 저장
조회한 Entity의 값을 변경할 때 시간이 자동 저장


[참고자료] : JPA Auditing 기능이란? - 준영이의 웹 까페 https://webcoding-start.tistory.com/53



연관 관계 매핑


@ManyToOne

: N:1 에서 N에 해당하는 엔티티가 1에 해당하는 엔티티와 연관관계를 매핑할 때 @ManyToOne 어노테이션을 씁니다.

@ManyToOne(fetch = FetchType.LAZY)

  • LAZY(지연): 필요할 때 데이터들을 로딩한다. - 모든 연관관계는 지연관계로 설정할 것.

@OneToMany

: 1에 해당하는 엔티티가 N에 해당하는 엔티티와 관계가 있음을 명시
이때, N에 해당하는 엔티티에서 ManyToOne이 설정 된 멤버변수를 mappedBy 합니다.

Member.java
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)

  • cascade=CascadeType.ALL
    : 엔티티의 영속성 상태가 변화할 때 연관된 엔티티도 함께 변화한다.
    cascade의 타입에는 PERSIST, MERGE, REMOVE, REFRESH, DETACH, ALL 6가지 속성이 있다.

@JoinColumn

실제 데이터베이스에서 해당 칼럼(외래키)의 이름을 설정하는 것입니다.



칼럼 별 세부 설정


@Column(...)

Ex.
@Column(nullable = false, length = 40)
@Column(columnDefinition = "VARCHAR(10)")
@Column(columnDefinition = "VARCHAR(15) DEFAULT 'ACTIVE'")

  • mysql은 문자열을 무조건 ''로 감싸야 한다.
  • 칼럼의 디폴트 값은 @ColumnDefault('ACTIVE') 같은 형태로도 가능함
profile
개발공부하는 잠만보

0개의 댓글