-
카테고리
-
세부 분야
백엔드
-
해결 여부
미해결
type(i) = Book 의 사용
21.03.09 22:28 작성 조회수 213
0
시간이 좀 지나서 자세히 기억은 안 나지만 이전 상속 관계 매핑 부분에서 TABLE_PER_CLASS 전략일 경우 Item만을 위한 테이블이 쓸 데 없이 생성되는 낭비를 막기 위해 어떠한 조치를 해주었던 기억이 납니다.
(abstract을 해줬던 거 같네요)
이같은 기억으로 미루어볼 때 dtype 속성을 사용해서 특정 자식 객체만 찾는 이 방식은 JOINED, SINGLE_TABLE 전략에서만 사용 가능할 거 같은데 제 추측이 맞을까요?
답변을 작성해보세요.
6
da-nyee
2021.05.21
이에 대한 결과가 궁금해서 '상속관계 매핑' 에서 진행했던 예제를 토대로 직접 실습을 진행해봤습니다.
다음은 Main 함수 코드입니다.
try {
Book book = new Book();
book.setName("bookA");
book.setAuthor("babo");
em.persist(book);
em.flush();
em.clear();
List<Item> result = em.createQuery("SELECT i FROM Item i WHERE TYPE(i) = Book", Item.class)
.getResultList();
for (Item item : result) {
Book book1 = (Book) item;
System.out.println("book1.getName() = " + book1.getName());
System.out.println("book1.getAuthor() = " + book1.getAuthor());
}
tx.commit();
} catch (Exception e) {
tx.rollback();
e.printStackTrace();
} finally {
em.close();
emf.close();
}
}
그런 다음 상속 전략을 JOIN, SINGLE_TALBE, TABLE_PER_CLASS으로 바꿔가며 쿼리 결과를 살펴봤습니다. (참고로 @DiscriminatorColumn 값은 기본값인 DTYPE, 나머지 테이블의 @DiscriminatorValue 값은 앞 글자의 대문자로 설정하였습니다.)
1. JOINED
LEFT JOIN을 하면서 ITEM의 DTYPE이 'B'인 조건을 만족하는 값을 찾는 SELECT 쿼리가 실행되는 것을 확인할 수 있었습니다.
Hibernate:
/* SELECT
i
FROM
Item i
WHERE
TYPE(i) = Book */ select
item0_.id as id2_5_,
item0_.name as name3_5_,
item0_.price as price4_5_,
item0_1_.artist as artist1_1_,
item0_2_.author as author1_2_,
item0_2_.isbn as isbn2_2_,
item0_3_.actor as actor1_9_,
item0_3_.director as director2_9_,
item0_.DTYPE as dtype1_5_
from
Item item0_
left outer join
Album item0_1_
on item0_.id=item0_1_.id
left outer join
Book item0_2_
on item0_.id=item0_2_.id
left outer join
Movie item0_3_
on item0_.id=item0_3_.id
where
item0_.DTYPE='B'
book1.getName() = bookA
book1.getAuthor() = babo
2. SINGLE_TABLE
SINGLE_TABLE 전략은 ITEM 테이블에 모든 값이 저장되므로 조인의 과정없이 ITEM의 DTYPE이 'B'인 조건을 만족하는 값을 찾는 SELECT 쿼리가 발생하는 것을 확인할 수 있었습니다.
Hibernate:
/* SELECT
i
FROM
Item i
WHERE
TYPE(i) = Book */ select
item0_.id as id2_3_,
item0_.name as name3_3_,
item0_.price as price4_3_,
item0_.artist as artist5_3_,
item0_.author as author6_3_,
item0_.isbn as isbn7_3_,
item0_.actor as actor8_3_,
item0_.director as director9_3_,
item0_.DTYPE as dtype1_3_
from
Item item0_
where
item0_.DTYPE='B'
book1.getName() = bookA
book1.getAuthor() = babo
3. TABLE_PER_CLASS
UNION을 통한 어마무시한 SELECT 쿼리가 발생한 것을 확인할 수 있었습니다. 그러나 위의 두 전략과는 다르게 DTYPE을 통해 만족하는 조건을 찾는 것이 아니라 'clazz_' 라는 속성을 통해 만족하는 조건을 찾는 것을 확인할 수 있었습니다. 이 clazz_는 TABLE_PER_CLASS 전략을 사용할 때만 생성되는 것 같았고, FROM 절의 서브 쿼리를 보면 Album, Book, Movie 테이블에 각각 clazz_의 값이 1, 2, 3으로 설정되는 것을 확인할 수 있었습니다.
Hibernate:
/* SELECT
i
FROM
Item i
WHERE
TYPE(i) = Book */ select
item0_.id as id1_5_,
item0_.name as name2_5_,
item0_.price as price3_5_,
item0_.artist as artist1_1_,
item0_.author as author1_2_,
item0_.isbn as isbn2_2_,
item0_.actor as actor1_9_,
item0_.director as director2_9_,
item0_.clazz_ as clazz_
from
( select
id,
name,
price,
artist,
null as author,
null as isbn,
null as actor,
null as director,
1 as clazz_
from
Album
union
all select
id,
name,
price,
null as artist,
author,
isbn,
null as actor,
null as director,
2 as clazz_
from
Book
union
all select
id,
name,
price,
null as artist,
null as author,
null as isbn,
actor,
director,
3 as clazz_
from
Movie
) item0_
where
item0_.clazz_=2
book1.getName() = bookA
book1.getAuthor() = babo
결론
JOINED, SINGLE_TABLE, TABLE_PER_CLASS 전략 모두 상속관계에서 TYPE 연산을 통해 특정 자식 클래스를 조회할 수 있었습니다. 그러나 JOINED, SINGLE_TABLE 전략은 DTYPE을 사용하고, TABLE_PER_CLASS는 clazz_ 라는 속성(?)을 사용합니다.
실습 내용이 많이 부족하고 어설프기 때문에 잘못된 점이나 부족한 점 있으면 많이 조언 남겨주세요 😅
0
김영한
지식공유자2021.03.10
안녕하세요. 현강님^^
제가 답을 바로 알려드릴 수도 있지만, 이런 부분은 스스로 한번 테스트를 해보면 더 많이 배우실 수 있습니다^^
그리고 테스트하고 결과를 남겨주시면 다른 분들에게도 도움이 될 거에요^^
감사합니다.
임현강
질문자2021.03.10
넵 답변 감사합니다.
강의의 코드를 따라치면서 듣다 보면 어느 순간부터는 그냥 기계적으로 타이핑하기에 급급할 뿐이고 내용에 대한 이해는 제대로 이뤄지지 않더라구요.
그래서 일단은 따라치지 않고 시청만 하면서 내용을 익힌 후 다시 한 번 돌려보면서 따라쳐보고 실습해보는 나름의 방식대로 학습을 진행하는 중입니다.
사실 직접 쳐보면 금방 알 수 있는 내용이란 걸 알면서도 이전부터 따라와놓은 코드가 없어서 질문을 드렸습니다;ㅎ
1회독(?)은 이제 거의 끝나가니 위 내용은 2회차 때에 실습해보도록 하겠습니다.
감사합니다^^
답변 2