본문 바로가기

FastCampus - 한번에 끝내는 Java|Spring 웹 개발/04 JPA

JPA Ch 4 Entity 기본 어노테이션들 - 패스트캠퍼스 챌린지 23일차

정줄차리고보니 노트북을 잘못 골라놨던

앞서 @Entity User 를 정의하면서 @Entity 와 @Id, @GeneratedValue 를 사용했었습니다. 엔티티를 정의하는 데에는 이 세 가지 외에도 더 다양한 어노테이션이 있습니다. 이전에는 기본값만으로도 충분해서 사용하지 않았던 그 어노테이션들을 살펴보는 시간이 되시겠습니다.

@Entity, @Id

skip >>

@GeneratedValue (*필드)

이 필드가 생성된 값이라는 걸 나타내는 어노테이션으로, @Id 와 함께 썼었습니다.

strategy 라는 값이 있습니다. enum GenerationType 4가지 중 하나의 값인데, 기본값은 AUTO 입니다.

  • TABLE - 별도의 테이블을 만들어 ID 생성을 관리합니다. (잘 안 쓰임)
  • SEQUENCE - DB가 제공하는 특수한 객체를 사용하여 순차적인 값을 부여합니다.
    H2 DB 가 이걸 쓰는게,
    call next value for hibernate_sequence;​
    가 매 삽입 쿼리마다 있었던 게 이 까닭입니다.
  • IDENTITY - DB가 제공하는 특수한 타입의 칼럼을 사용해 ID를 만듭니다. 프로덕션에 들어가는 MariaDB, MySQL 등에서 사용합니다. 오라클 구버전 빼고...
  • AUTO - 아시죠?

SEQUENCE 와 IDENTITY 의 설명이 비슷해서 헷갈렸는데 저만 그런 게 아니었나봅니다.
https://stackoverflow.com/a/8955097

@Table (*엔티티)

테이블의 이름, 인덱스, uniqueConstraint 지정 등에 사용합니다. @Entity 만 지정했다면 뭐 @Id가 index 고 테이블의 이름은 엔티티의 이름이겠죠? 보통은 쓸 일이 없다는 얘깁니다. 그래도 여러 칼럼으로 키를 잡거나 기존 시스템에 매핑할 때 같은 때에는 필요하니까요...

  • name - ㅎㅎ 아시잖아요
  • indexes - 인덱스를 잡습니다. {@Index(columList="name")}
  • uniqueConstraints = { @UniqueConstraint(columnNames={"email"}) }

주의: indexes, uniqueConstraint 는 JPA가 만들어낸 DDL 에만 적용됩니다. 데이터베이스를 이 어노테이션이 있는 상태로 테이블을 만들었다 라면 적용되어있겠지만, 기존 데이터베이스에 맞춰서 엔티티를 짰거나 그러면 당연하게도 적용이 되어있지 않을 겁니다. 그러니까, 실제 데이터베이스의 제약과 다를 수 있습니다. 이런 상황에서는 insert 도 select 도 제약조건의 영향을 받지 않겠죠. 그도 그럴 게 데이터베이스에 제약조건이 안 들어있으니까요.

@Column (*필드)

칼럼의 상세정보를 조절합니다. 필드에다 적용하겠죠? 이게 없으면 다 기본값일 거구요.

  • name: 아시죠? 이것도 기존 DB의 컬럼명에 맞출 때 유용합니다.
    • 세상에 전혀 보기 싫은 케이스를 강의에서 들어버렸는데요, 옛날에는 칼럼명으로 약어를 썼대요... createdAt 을 crtd 같이 줄인다던가... 그만 제발 그만
  • nullable: DDL의 해당 필드에 not null 조건을 넣을건지 여부.
    • DDL이라고 했죠? 위에 설명했던 내용이 적용됩니다.
    • 런타임에 적용이 안 될 수도 있지만, 테스트에서 확인하기 위한 용도로 많이 쓰인다고 하네요. 테스트할 때에는 기존 DB를 쓰는 게 아니라 DDL 을 만들어서 넣으니까요.
  • unique: DDL의 해당 필드에 unique 조건을 넣을건지 여부.
    • 두 번 말하면 입이 아프겠죠?
    • 다만, @Table 에서 정의할 수 있는 uniqueConstraint 와는 전혀 다른 거라는 것 정도는 한 번 짚고 넘어가주는 게 좋습니다. 얘는 email 처럼 필드에 unique 한 값이 들어가야 하는거고 uniqueConstraint 는 한 개 이상의 쌍에 통째로 고유 제약을 거는 거니까요. 뭐 칼럼을 하나만 지정하면 기능상으로는 같은 게 되겠습니다만...
  • insertable, updatable 은 DDL 뿐만이 아니라 insert / update 쿼리에도 적용됩니다.
    • 그도 그럴 게, 삽입할 수 있는지 / 업데이트할 수 있는지 여부잖아요?
    • 이게 false 가 되면 각각의 쿼리에서 해당 칼럼이 아예 제외가 됩니다.
    • 완벽한 예제:
      // update 쿼리에서 칼럼째로 아예 안 나옴!
      @Column(updatable = false)
      private LocalDateTime createdAt;

@Transient (*필드)

오브젝트 매퍼에서 @Ignore 하던 거 있잖아요? 그거에요. 개인적으로는 이런 게 DTO에 들어가는 게 바람직하지 않다고는 생각하는데 뭐 계산된 프로퍼티라던가에는 필요하지 않겠어요? 근데 Java에 그런 거 없지 않나... ㅋㅋ 떵바 ㅋㅋ 전자정부표준프레임워크가 만들어낸 환상의 Java 8 환경 ㅋㅋ

enum 처리 (주의 필요!) - @Enumerated (*필드)

주의가 필요한 이유는 단순합니다. 데이터베이스에 기본적으로는 ORDINAL 로 매핑되거든요. 숫자로 들어간다는 얘기입니다. 그래서 enum 의 필드 순서가 바뀌면 대응되는 값도 바뀌는 대참사가 일어납니다...

(* 코딩 호러 짤이 여기에 있다고 상상해주세요)

enum Gender {
   Male,   // 0
   Female, // 1
   Other   // 2
}

// 리팩터링하다가 실수로 순서를 바꾸면

enum Gender {
   Other,  // 0
   Female, // 1
   Male    // 2
}

이런 일을 방지하기 위해, enum 필드를 ORDINAL 대신에 STRING 으로 박아넣는 방법이 있습니다.

생략
public class User {
생략
    @Enumerated(EnumType.STRING)
    private Gender gender;
}

강의에서는 정말로 0과 1이 나오는 걸 나중에 배울 @Query 를 통한 nativeQuery 로 확인합니다.
(저는 order by 를 넣어야 했어요 - limit 1 은 제일 끝에 들어가더라구요 ㅋㅋ)

interface UserRepo: 아무튼_상속 {
    @Query(value = "select * from user order by id desc limit 1;", nativeQuery = true)
    fun findRawRecord(): Map<String, Any>
}
    @Test
    @Transactional
    open fun test_enum() {
        userRepo.saveAndFlush(User("mmartin", "mmartin@fastcampus.co.kr").apply { gender = Gender.Woman })
        println(userRepo.findRawRecord()["gender"])
    }

(실습할 땐 Female 이 생각이 안 났음, 분명히 강의에서 봤는데...)

    order by
        id desc limit 1;
1

이번에는 알아는 둬야하는 Entity 의 다른 어노테이션을 알아봤다면, 다음에는 엔티티의 "리스너" 라는 자주 사용하는 기능을 알아본다네요.

근데 친구한테 물어봤는데 쿼리메소드 잘 안 쓴다던데

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.
패스트캠퍼스: https://bit.ly/37BpXiC

#패스트캠퍼스 #패캠챌린지 #직장인인강 #직장인자기계발 #패스트캠퍼스후기 #한번에끝내는JavaSpring웹개발마스터초격차패키지Online

공백제외 500자라는 조건이 있으니까 매번 글을 다 쓰고 (리스트에 들어간 항목들을 제외하고) 꼭 마스토돈 글쓰기란에 붙여넣기 해서 500을 넘는지 체크를 하거든요? 그런데 이번에는 그냥 넉넉히 달성해버리네요. 매번 학습하는 내용들이 어느정도 분량이 있다보니 설명만 주르륵 적더라도 500자는 간단히 넘겨버리... 간당간당한 적도 있어서 살짝 ㅋㅋ

요즘 글쓰기 습관에 끝에 ㅋㅋ 가 붙는 거 같은 모습이 좀 잦은데, 이렇게 쓰면 "기분이 조크든요"가 되는 거 같습니다. 아무래도 뭘 하든 행복한 게 제일 아니겠어요? 살짝 걱정되는 건 너무 오타쿠같아보이지 않을지... 뭐 지금 글도 이미 충분히 가독성이 떨어져있다고는 생각합니다. 글을 쓸 때 한 번 더 퇴고하는 게 중요하겠죠. 하지만 굳이 되돌아가서 한 번 다시 살펴보기는 번거로우니 쓸 때 한 번 더 확인을 하게 되더라구요. 뭐 점점 나아지겠죠~