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

Tony님의 프로필 이미지
Tony

작성한 질문수

실전! 코틀린과 스프링 부트로 도서관리 애플리케이션 개발하기 (Java 프로젝트 리팩토링)

14강. Kotlin과 JPA를 함께 사용할 때 이야기거리 3가지

Kotlin/JPA Inheritance 질문

작성

·

890

1

안녕하세요, Kotlin jpa 코드를 쓰다보니 레퍼런스 코드를 찾기가 쉽지 않은데요.

https://ict-nroo.tistory.com/128

이 블로그 글에 있는 상속 예제 코드를 코틀린으로 옮기면 어떻게 해야할까요?

open class 문제나 primary constructor 로 상위 클래스를 구현하다보니 상속 부분 구현하는데서 생각보다 어려움을 겪고 있습니다.

답변 2

1

최태현님의 프로필 이미지
최태현
지식공유자

안녕하세요! Tony님~!!! 즐거운 한가위 보내셨나요?!! 😊 추석이라 답변이 늦었습니다...! 죄송합니다! 😢

빠르게 답변드리자면, 아래와 같이 바꾸어 볼 수 있습니다!


@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
class Item(
  val name: String,

  val price: Long,

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  val id: Long? = null,
)

@Entity
class Album(
  name: String,
  price: Long,
  val artist: String,
) : Item(name, price)

@Entity
class Movie(
  name: String,
  price: Long,
  val director: String,
  val author: String,
) : Item(name, price)

@Entity
class Book(
  name: String,
  price: Long,
  val author: String,
  val isbn: String,
) : Item(name, price)

이제 여기서 다른 상속 전략을 사용하시면 (그에 따라 어노테이션도 조금 바꿔주실 수 있고요!) 되어요~!!

name과 price에 대해서는 생성자의 파라미터로만 받아 상위 클래스를 초기화하는데 바로 사용했는데요! 아래와 같이 override val을 붙여도 무관합니다.


@Entity
class Book(
  override val name: String,
  override val price: Long,
  val author: String,
  val isbn: String,
) : Item(name, price)

override val을 사용하게 되면 Java클래스로 생각했을 때 Book에도 name와 getName()이 있고, Item에도 name과 getName()이 존재하게 되는데요, 실제 사용에는 큰 문제가 없었습니다!

 

상속 예제를 따라하시는데 어려움이 있으시다면, 우선 JPA를 생각하지 않은 상태에서 상위 클래스와 하위 클래스를 만들어 보신 다음 어노테이션을 추가로 붙여보시면 조금 더 쉬우실 거에요~!! 😊

감사합니다!!! 🙏 남은 연휴도 행복한 시간 되세요~!!

0

Tony님의 프로필 이미지
Tony
질문자

친절한 답변 감사합니다.

혹시 primary constructor 에 구현하는 것과 class 내부에 구현하는 것의 차이가 어떤 차이가 있을까요?

그리고 primary constructor 구현때에 var 와 val 구분도 어떻게 해서 구현하시는지 궁금합니다!

그리고 추가로 이렇게 상속을 할때 API에서는 모든 ITEM을 받고 싶다고 하면 타입을 어떻게 정의해주는게 좋을지 궁금합니다.

Item 으로 했더니 세부 타입들이 무시되더라구요!

최태현님의 프로필 이미지
최태현
지식공유자

안녕하세요~!

  • 혹시 primary constructor 에 구현하는 것과 class 내부에 구현하는 것의 차이가 어떤 차이가 있을까요?

이 질문은 아마 변수를 주 생성자에 넣는 것과 class 내부에 넣는 것의 차이를 여쭤보신 것 같아요! 문법적으로는 생성자를 호출 할 때 해당 파라미터를 의무적으로 받아야 하는지, 그렇지 않은지의 차이가 있고 의미론 적으로는 14강에서 말씀드렸던것처럼 큰 차이가 없습니다! 😊

 

val과 var의 차이는 불변와 가변 여부인데요! 이전 강의인 자바 개발자를 위한 코틀린 입문(Java to Kotlin Starter Guide) 의 1강을 참고해보시면 좋을 것 같아요!!!!

 

  • 그리고 추가로 이렇게 상속을 할때 API에서는 모든 ITEM을 받고 싶다고 하면 타입을 어떻게 정의해주는게 좋을지 궁금합니다.

  • Item 으로 했더니 세부 타입들이 무시되더라구요!

에 대해서는 제가 질문을 이해하지 못했습니다! 🥲

추상화된 인터페이스를 원하시는거라면, https://calatheas.tistory.com/entry/Jackson-%EC%9E%91%EC%84%B1%EC%A4%91-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%ED%95%98%EC%9C%84%ED%81%B4%EB%9E%98%EC%8A%A4-%EB%93%A4%EC%9D%98-deserializing 와 같이 @JsonTypeInfo 어노테이션을 찾아보시면 도움 되실 것 같습니다!

Tony님의 프로필 이미지
Tony
질문자

Item 이 Movie, Album 등의 세부 상속 타입을 가지고 있을때, 리턴 타입을 어떻게 해야하는지였습니다..!

var/val 질문도 기본적으로 세부 프로퍼티 중 일부는 계속 변하는 값을 가질 수 있을건데, 현재 보여주신 예시 코드에는 모두 val 로만 정의되어 있어서요..!

var 로 또 정의하게되면 setter 를 막아주는 조치를 취하는데 (protected set) 이게 primary constructor 에서는 불가능하지 않은가 싶어서 질문 드렸습니다.

최태현님의 프로필 이미지
최태현
지식공유자

아하~!! 제가 코드를 보지 않고 정확한 말씀을 드리기는 어렵지만.. 😢 추상화된 리턴 타입 말씀이시라면, 가장 상위 타입 (abstract class 또는 interface) 을 반환 타입으로 지정하시고 실제로는 구체화된 하위 타입을 return 하시게 되면 Jackson에서 알아서 역직렬화를 해줍니다~ 😊

 

아 그렇군요!! 제가 작성한 예제에서는 변경되는 지점이 없어 모두 val로 표기하였어요!! 일종의 습관입니다!! ㅎㅎㅎㅎ

네네 맞습니다, primary constructor 내에서 var로 선언도 하고 setter도 막아주는 것은 불가능합니다 ㅠㅠ

Tony님의 프로필 이미지
Tony

작성한 질문수

질문하기