Hibernate Naming Strategy

LST·2023년 2월 22일
0

문제상황

팀 프로젝트를 하면서 각자 데이터베이스 설계와 기능구현을 나눠서 진행했는데 이 과정에서 데이터베이스의 테이블과 엔티티가 매핑되지 않는 문제가 발생하였다.
Table(plan)

planIdstartYear
12023

Entity(Plan)

@Entity
public class Plan {
	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long planId;
    
    private Integer startYear;
}

이 상태로 실행을 하고 해당 테이블에 접근하는 코드를 실행하니 <Unknowm column 'start_year' in 'field list'> 에러가 발생했다. 즉 테이블에 start_year 필드가 없다는 것으로 해석됐다. yaml 파일에서 <jpa.show-sql:true> 로 설정하고 자동 생성된 sql 문장을 확인하면 planId는 plan_id, startYear은 start_year 로 매핑하고 있다.

Hibernate: 
    select
        plan0_.plan_id as plan_i1_1_0_,
        plan0_.start_year as plan2_1_0_
    from
        plan plan0_ 
    where
        plan0_.plan_id=?

Naming Strategies(명명 전략)

Hiberbate는 엔티티와 테이블, 엔티티와 칼럼명을 매핑하는 다음의 두가지 단계가 있다.

  1. 적절한 논리적 이름(logical name)을 결정한다. 논리적 이름은 명시적으로 개발자에 의해 @Table (name="~"), @Column (name="~") 를 작성하거나 암시적으로 Hibernate의 ImplicitNamingStrategy 를 통해 결정할 수 있다.

  2. 이 논리적 이름을 PhysicalNamingStrategy에 정의된 전략을 통해 물리적 이름으로 변환한다. 기본값은 앞의 논리적 이름을 그대로 사용한다.

    [출처 : 링크텍스트]

  • ImplicitNamingStrategy
    엔티티와 데이터베이스 테이블을 매핑할 때, 혹은 특정 애트리뷰트를 테이블의 칼럼에 매핑할 때 명시적으로(애노테이션을 사용하여) 매핑하지 않았다면 암시적으로(Implicitly) 테이블명과 칼럼명을 매핑시켜줘야 한다. org.hibernate.boot.model.naming.ImplicitNamingStrategy 에는 ImplicitNamingStrategy 인터페이스와 명시적 이름이 없을 경우 논리적 이름을 결정하는 전략들의 구현체가 있다. 따라서 개발자가 직접 전략을 만들어 사용할 수도 있다. 예시
  • PhysicalNamingStrategy
    PhysicalNamingStrategy는 논리적 JPA 객체 이름에 기반하여 실제 DB에 사용되는 물리적 이름을 제공한다. ImplicitNamingStrategy와 마찬가지로 인터페이스가 존재하고 구현체가 존재하여 개발자가 직접 전략을 만들어 사용할 수 있다. 기본적으로 카멜 케이스를 언더바(_)로 바꾸며 엔티티의 변수명을 그대로 사용하고 싶다면 org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl 로 설정하면 된다.

문제해결

두 가지 방법이 존재한다. 어노테이션을 사용하여 모든 변수에 칼럼명과 테이블명을 지정해주거나 물리전 전략을 변경한다. 전자의 경우 엔티티가 많다면 모든 변수에 명시적 이름을 지정하기는 불가능하다. 따라서 설정파일에서 물리적 전략을 추가해준다.

spring.jpa.hibernate.naming.physical-strategy : org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

0개의 댓글