멍두의 개발새발
[JPA] Entity에서 @Table, @Entity, @Column의 name을 정의해주어야할까? 본문
Entity를 사용하다보면, Table이나 Column명이 Database와 불일치하여 name=''으로 정의를 해주어야하는 경우가 있다.
그렇다면 hibernate가 자동으로 명명해주는 이름과 Table이나 Colum의 이름이 동일할 때도 name을 정의해주어야할까?
일단 @Column, @Table, @Entity의 name 속성을 정의하면 어떤일이 발생하는지 다시 한번 짚고 넘어가자.
@Column
- Column의 속성들을 지정해주는 어노테이션
- name 지정 시, DB column명과 매핑해주는 어노테이션 (create 사용 시DDL에서도 사용)
- 없다면 필드명을 통해 자동 생성된 컬럼명으로 매핑이 된다.
@Table
- name 지정 시, DB Table명과 매핑해주는 어노테이션 (create 사용 시 DDL에서도 사용)
- 없다면 클래스명으로 자동 생성된 테이블명으로 매핑이 된다.
@Entity
- Entity임을 명시해주는 어노테이션
- name을 지정 시, Entity의 이름을 지정해줄 수 있다. (JPQL에서 사용)
- 없다면 클래스명으로 지정된다.
참고 : 이름을 자동으로 지정해줄 때는 SpringImplicitNamingStrategy 로 snake_case적용
이때 Entity와 Table을 보면서 Entity의 이름? Table의 이름? Entity가 Table아닌가? 할 수도 있는데, 둘은 명확히 다르다.
두 어노테이션을 직접 적용해보면서 둘의 차이를 살펴보자
1. Entity name만 존재할 때
@Entity(name = "hi")
public class TableName {
}
- hibernate query : create table hi;
- entity명 : hi
- table명 : hi
2.. Table name만 존재할 때
@Entity
@Table(name = "hi")
public class TableName {
}
- hibernate query : create table hi;
- entity명 : TableName
- table명 : hi
- JPQL 작성 시 hi로 작성하면 컴파일 오류
🚨 Entity만 정의하면 Table에도 적용이 되지만, Table만 적용하면 Entity에는 적용이 되지 않는다.
3. Table, Entity 둘 다 name이 존재할 때
@Entity(name = "table_name")
@Table(name = "tablename")
public class TableName {
}
- hibernate Query : create table tablename
- entity명 : table_name
- table명 : tablename
4. name을 정의해주지 않았을 때
@Entity
public class TableName {
}
- hibernate Query : create table table_name
- entity명 : table_name
- table명 : table_name
그렇다면 다시 본론으로 돌아와서..
Hibernate에서 지정해주는 이름과 Entity, Table, Column 명이 동일한 경우, 명시적으로 이름을 지정해주어야 하는가?
나의 생각은 Table, Column은 정의를 해주되, Entity는 JPQL을 많이 사용하는 Repository인 경우 정의를 해주자 라고 생각한다.
먼저 Table과 Column를 정의하는 것이, 유지보수에 훨씬 유리하다.
native Query, DDL, orm mapping 등 다양한 곳에서 name 속성이 사용이 되는데, 만약 정의하지 않았다면
- 후에 클래스명, 필드명이 변경이 되었을 때 Mapping을 위해서 정의를 해주어야한다. 누락 시 RuntimeError발생한다.
- 컴파일 타임에 잡히지 않는 문자열 nativeQuery를 전부 찾아가서 고쳐야한다.
또한, 클래스명, 필드명은 shema보다 변경 가능성이 높다. 클래스명, 필드명의 변경 영향 범위를 최소화할 수 있다. 반대로 schema가 변경이 되었을 때도, 해당 annotation만 찾아가서 고치면 된다.(이 때 nativequery는 전부 고쳐야하겠으나, schema가 변경되어서 nativequery를 수정하는 것은 당연한 일이라고 생각된다.) 이를 통해 구조적 안정성을 높일 수 있다.
다음으로, Entity는 JPQL을 많이 사용하는 Repository인 경우 정의를 해주면 된다
Entity는 JPQL에서 사용이 되는데, JPQL은 객체 모델 관점에서 query를 작성하는 기능이다. 클래스명이 변경이된다면 JPQL도 변경되는 것은 당연한 것이라고 생각됐다. 둘이 불일치될 경우 가독성이 저해될 수 있다고 느꼈다.
또한 JPQL은 오류를 컴파일 타임에 잡을 수 있다. 이는 native query와 큰 차이점이자 장점이다.
그러나 name을 미리 지정해준다면, JPQL은 클래스명과 무관하게 안정적으로 유지될 수 있다. 만약 JPQL을 많이(?) 정의해서 사용하는 곳이라면 선제적으로 name을 지정해주어, 변경 영향 범위를 최소화하는 것도 유지보수를 위한 선택이 될 수 있다고 생각한다.
마무리하며
이 고민을 하면서
- 결국은 바뀔 것이라는 가정 하에 미리 정의를 해주는 게 옳은가?
- 아직 발생하지 않을 일을 미리 걱정하면서 현재 시점에는 의미가 없을 수도 있는 코드를 작성해야하는 건가?
- 어디까지는 걱정하고 어디까지는 걱정하지 않아도 되는거지?
하는 의문이 있었다.
최근 읽은 좋은코드 나쁜코드에서 이 의문을 어느정도 해소해주는 문구가 있었다.
이 문구를 남기면서 글을 마무리한다.
고품질 코드를 작성할 때 가장 중요한 고려사항 중 하나는 다른 개발자가 변경하거나 코드와 상호작용할 때 발생할 수 있는 문제는 없는지, 또 발생한다면 그 문제를 어떻게 완화할 수 있을지를 이해하고 선제적으로 조치하는 것이다.
코드를 작성할 때 고려할 것 3가지는
1. 나한테 명백하다고 해서, 다른 사람에게도 명백한 것은 아니다.
2. 다른 개발자는 무의식중에 여러분의 코드를 망가뜨릴 수 있다
3. 시간이 지남에 따라 자신의 코드를 기억하지 못한다.
이다.
'Programming > Spring' 카테고리의 다른 글
[Spring] 스프링 빈 왜 쓰세요 ? (4) | 2025.06.09 |
---|---|
[JPA] @NotNull VS @Column(nullable = false) (1) | 2025.05.26 |
[JPA] Entity에서 사용되는 Annotation 정리 (@Table, @Entity, @Column, @Enumerated, @Temporal .. ) (2) | 2025.05.26 |
[스프링] DTO에 @NoArgsConstructor와 @Gettter이 필요한 이유 (3) | 2024.07.30 |
[스프링] - findByIN절, jdbc batchUpdate (bulk Insert)로 쿼리 개선 (0) | 2024.05.29 |