티스토리 뷰

실무를 하다 보면 종종 다른 데이터베이스에 같은 이름의 테이블이 존재하게 된다.

예를 들어, A와 B 데이터베이스에 Category라는 테이블이 있고, 하나의 프로젝트에서 두 개의 엔티티를 만들어 사용할 수 있다.

 

# 스키마가 다른 같은 이름의 테이블

create table schema_a.category
(
    category_seq int auto_increment primary key
);

create table schema_b.category
(
    category_seq int auto_increment primary key
);

 

보통 이런 경우 테이블 명칭을 그대로 사용하여 엔티티 클래스 이름으로 사용하여 다음과 같이 사용할 수 있다.

schema_a에 있는 category 엔티티
schema_b에 있는 category 엔티티

나는 막연하게 @Table에 스키마와 테이블 명칭을 지정해두었으니 해당 엔티티를 사용할 때 문제없을 줄 알았다.

queryDSL 사용예시

왜냐하면 위 사진과 같이 QClass를 통해 패키지 경로가 지정된 채로 사용되어 query가 generated될 줄 알았기 때문이다.

하지만, 위 코드를 실행시켜보면 보기좋게 에러가 발생한다. 

select category
from com.example.blog.entity.schema_b.Category category
where category.categoryASeq = ?1

 

분명 schema_a 패지키 경로에 있는 category엔티티를 사용하였지만, 실제 쿼리는 schema_b로 나가면서 필드를 찾을 수 없는 에러가 발생한다.

처음에는 QueryDSL이나 기타 다른 라이브러리 오류인 줄 알았지만...

태생부터  entity명칭은 다른 패키지라 하더라도 같으면 안 된다는 규칙(?)이 있었다.

https://stackoverflow.com/questions/30590324/select-a-default-entity-when-two-or-more-entities-with-same-name-exist-spring

 

Select a default Entity when two or more Entities with same name exist - Spring Boot, Spring Data JPA,

I'm using spring data jpa for persistence. Is there a way where one entity can be marked as default if more than one entity exists with the same name. Something like @Primary annotation used to res...

stackoverflow.com

https://www.objectdb.com/java/jpa/entity/types#Entity_Classes_

 

JPA Persistable Types

JPA Persistable Types The term persistable types refers to data types that can be used in storing data in the database. ObjectDB supports all the JPA persistable types, which are: User defined classes - Entity classes, Mapped superclasses, Embeddable class

www.objectdb.com

Entity classes are represented in queries by entity names. By default, the entity name is the unqualified name of the entity class (i.e. the short class name excluding the package name). A different entity name can be set explicitly by using the name attribute of the Entity annotation:

Entity names must be unique. When two entity classes in different packages share the same class name, explicit entity name setting is required to avoid collision.

 

기술적으로 어떤 이유인진 모르겠지만, 유니크해야 한다고 한다..

컴파일 시에는 패키지 경로로 체크하기 때문에 오류 표시가 안 나지만, 실제 런타임 시 쿼리가 만들어질 때 오류가 발생하는 케이스이므로 주의해야겠다.

 

+)

테스트하다가 발견한 내용으로,

hibernate 5.3.9 버전에서 해당 코드를 돌리면 단순히 위와 같이 쿼리를 만들 때 오류가 나지만

hibernate 5.4.x 버전부터는 아래와 같이 오류의 이유가 정확히 출력된다.

Caused by: org.hibernate.DuplicateMappingException: The [com.example.blog.entity.schema_a.Category] and [com.example.blog.entity.schema_b.Category] entities share the same JPA entity name: [Category] which is not allowed!

 

그냥 궁금해서 찾아보니 org.hibernate.boot.internal.InFlightMetadataCollectorImpl 클래스에 addEntityBinding이 실행되면서 엔티티가 바인딩될 때 엔티티 클래스 이름이 같은 놈이 있는지 체크하는 로직이 추가된 것으로 보인다.

5.3.9 버전에도 entityName을 체크하는 로직은 있었지만, jpaEntityName을 비교하는 로직도 추가된 것이다.

 

참고로, entityName은 패키지 경로를 포함한 엔티티 클래스의 이름 같고, jpaEntityName은 @Entity의 name속성에 정의된 이름 같다.

 

@Entity 속성 name까지 각각 다 지정하여 분기를 피한다 하더라도 결국 exception을 만나 동작하지 않게 된다.   

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함