인프런 커뮤니티 질문&답변

시큐웨어님의 프로필 이미지
시큐웨어

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

프로젝션(SELECT)

엔티티를 상속 받는 DTO 만들어도 되나요?

작성

·

615

1

=========================================
[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)

[질문 내용]
 
 

안녕하세요. 영한님..

영한님 강의 너무 재밌게 잘 보고 있고 쉽고 간결한 설명에 매일 감탄 하며 공부중인 직장인입니다.

질문드리기전에 상황을 설명하면 이렇습니다.

(이해하기 쉬우시게 한글로 적겠습니다)

'병원' , '환자' 라고 하는 두 엔티티가 있습니다.

환자는 병원을  참조하고 있습니다(FK)

 

@Entity
@Getter @Setter
@Builder @EqualsAndHashCode(of = "id")
@AllArgsConstructor @NoArgsConstructor
public class 병원 {

@Id @GeneratedValue
private Long id;

private String name;

. . . .

// 환자 수
@Transient
    private Integer 환자수;
}

 

@Entity
@Getter @Setter
@EqualsAndHashCode(of = "id")
@AllArgsConstructor
@NoArgsConstructor
public class 환자 {

// 환자 아이디
@Id @GeneratedValue
@Column(name = "PAT_ID")
private Long id;

// 병원
@ManyToOne
@JoinColumn(name = "HOSP_ID")
private 병원 병원;

. . . .
}

 

위와 같이 두 엔티티가 존재하는데

병원 리스트를 검색하면서 각 병원에서 수용중인 환자 수를 같이 하고 불러오고 싶습니다.

 

이를테면 환자수가 1명이상인 병원목록을 불러온다했을때 

이걸 SQL로 작성하면

SELECT h.*,
( SELECT COUNT(*) FROM patient WHERE hosp_id = h.hosp_id ) as '환자수'
FROM hospital h
WHERE ( SELECT COUNT(*) FROM patient WHERE hosp_id = h.hosp_id ) > 1;

(사실 이게 효율적인 SQL인지도 모르겠습니다만, 전 이렇게 보통 씁니다..)

처럼 작성할 수 있을건데요

 

이럴때 세가지 질문이 있습니다.

1. 병원 엔티티 클래스에 '환자수' 라는게 있는게 일단 맞는지 부터가 문제입니다.  병원 리스트를 조회할때  환자수가 몇명인지 정보도 같이 필요한 페이지도 있고 필요가 없는 페이지도 있습니다.  

단, 환자수 정보가 필요할때는 '몇명 이상의 환자가 있는 병원 목록'과 같이 (위 SQL과 같이) where 절에 조건도 같이 붙게 됩니다.

환자수는 DTO로 따로 빼는게 맞을까요?

 

2.  (1번질문에서 따로 빼는게 좋겠다고 하였을때)

환자수를 포함하는 병원DTO를 만든다고 했을때 사실 그 DTO는 병원의 모든 필드가 필요 합니다.

그래서 하려면  아래처럼 병원을 상속받는 식이 되어야 할텐데 이렇게 DTO 클래스가 엔티티 클래스를 상속받아도 문제가 없고, 이렇게 사용하는게 일반적으로 현업에서도 많이 있는 일인가요?


public class 병원출력DTO extends 병원 {

private Integer 환자수;
}

 

3. 제가 하고자하는 것 ( 엔티티에 있는 모든 정보 + 서브쿼리를 통한 추가정보를 같이 불러오고 서브쿼리를 이용한 WHERE절 ) 이 굉장히 일반적으로 많이 쓰이는 것이라 분명 JPA 프로그래밍으로 충분히 쉽게 하는 방법이 이미 있을것 같은데 지식의 끊이 짧다보니

어떤 방법을 써야하는지 감을 못잡겠습니다.

 

SELECT h.*,
( SELECT COUNT(*) FROM patient WHERE hosp_id = h.hosp_id ) as '환자수'
FROM hospital h
WHERE ( SELECT COUNT(*) FROM patient WHERE hosp_id = h.hosp_id ) > 1;

이런 것을 하기위해 제가 뭘 찾아보고 공부하면 되는지 키워드나 팁를 알려주실수 있을까요 (QueryDsl을 활용하면 될것 같긴한데.. )

답변 1

3

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 시큐웨어님

1,2 완전히 별도의 DTO로 뽑아야 합니다. 엔티티에는 순수한 데이터가 들어가야지 어떤 특정 계산의 결과값이 들어가면 안됩니다. 추가로 엔티티를 상속받지 말고, DTO를 만들어주세요. 엔티티와 DTO를 잘 분리해서 개발하는 것이 핵심 포인트입니다.

3. JPQL도 서브쿼리를 지원합니다. 단 from 절의 서브쿼리는 지원하지 않습니다. 해당 쿼리의 경우 JPQL의 new 명령어를 사용해서 DTO로 결과를 뽑으시면 됩니다.

감사합니다.

시큐웨어님의 프로필 이미지
시큐웨어

작성한 질문수

질문하기