개발 이론/JPA

[JPA] JPA엔티티에 기본생성자가 필요하다?

dal_been 2023. 11. 10. 11:39
728x90

JPA는 엔티티에 기본생성자, 즉 매개변수를 받지 않는 생성자를 만드는 것을 강제하고 있다.

물론 기본 생성자 없이도 정상적으로 작동하는 경우가 있지만 공식 스펙에따르면 기본생성자가 있어야한다고 기재되어있다.

 

그렇다면 왜 기본 생성자를 만들도록 강제할까??

 

앞서 기본 생성자를 강제하는 경우 @RequestBody와 @ModelAttribute에 대해서 알아봤다.

그중에서도 @RequestBody는 Reflection을 이용해 필드, 메서드 등의 클래스의 모든 정보에 접근하여 매핑해주었다.

다만 Reflection은 생성자 호출을 할 수없었다. 그래서 기본생성자를 강제하였다. 

 

https://haebing.tistory.com/72

 

[Spring] @ModelAttribute와 @RequestBody에 대해

컨트롤러로 들어오는 데이터 객체를 매핑하는 어노테이션으로 @ModleAttribute와 @RequestBody가 있다. @ModelAttribute는 여러개의@RequestParam을 하나의 객체로 매핑할때 쓰이고 @RequestBOdy는 Json형태로 들어

haebing.tistory.com

 

JPA도 데이터를 DB에서 조회해온 뒤 객체를 생성할때 Reflection을 사용한다. 때문에 기본 생성자로 객체를 생성하여 필드값을 매핑해준다

 

 

그런데 왜 JPA에서 Reflection을 사용할까?

 

그 이유는 엔티티로 어떤 타입을 생성할지  JPA에서는 알 수 없기 때문이다. 다시 말해 프레임워크나 라이브러리는 사용자가 정의할 구체 클래스 정보를 알 수 가 없다. 때문에 어떤 타입으로 엔티티를 만들기 위해서는 Reflection을 사용해야한다

 

 

그렇다면 기본생성자가 private이여도 되나?

 

@RequestBody에서는 기본 생성자가 private 이어도 상관없다. 그럼 엔티티도 해당되나?

 

음...객체 생성만 바라본다면 맞는 얘기다. 하지만 엔티티에는 프록시 라든지 lazy loading이있다

JPA 엔티티  조회에 있어 즉시 로딩과 프록시로 가짜 객체를 넣은 뒤 해당 객체의 정보가 필요할때 엔티티를 조회하는 즉시 로딩이 있는데

여기서는 생성자가 private이면 안된다(프록시와 지연로딩때문에)

 

왜???

엔티티의 프록시가 원본 엔티티를 상속해서 생성되기 때문이다.

지연로딩의 과정을 보면 프록시 객체가 실제 객체가 필요한 시점에서 프록시가 참조하고 있는 원본 엔티티에서 조회한다

 

다시말해 프록시는 부모 객체인 원본 엔티티를 super로 생성자를 호출해야하는데 private이면 상속받은 클래스에서 호출할 수 없다. 

여기서 주의할점은 이 부분에 대해서 컴파일 시점에 오류가 발생하지 않는다. 아예 기본생성자가 없는 경우 경고가 뜰 수 는 잇지만 접근 제어자와 관련된 예외는 런타임예외로 처리된다

 

 

따라서 public 혹은 protected 기본 생성자를 꼭 만들어야한다