Lombok으로 Entity를 만들 때 사용하는 생성자 관련 어노테이션을 총정리해보자.
크게 3가지가 있다.
1. @NoArgsConstructor
new User()와 같이 파라미터가 없는 기본 생성자를 생성한다.
중요한 점은, JPA는 DB에서 데이터를 조회해서 데이터를 만들 때 이 기본 생성자를 반드시 필요로 한다는 것이다!
세부 옵션으로는 다음이 있다.
access
접근 제어자(public, protected 등)를 지정한다.
@NoArgsConstructor(access = AccessLevel.PROTECTED)
- PUBLIC: 모든 곳에서 접근 가능하다.
- PACKAGE: 같은 패키지 내에서 접근 가능하다. Java의 default와 같다.
- MODULE: 같은 모듈 내에서 접근 가능하다. 모듈은 여러 패키지를 포함하는 더 큰 단위이긴 한데, 자바 모듈 시스템을 사용하지 않는 일반 프로젝트에서는 PACKAGE와 차이가 거의 없다.
- PROTECTED: 같은 패키지 또는 자식 클래스에서 접근 가능하다. JPA 엔티티에서는 외부에서 무분별하게 생성하는 것을 막기 위해서 이 옵션을 주로 사용한다.
- PRIVATE: 내부 클래스에서만 사용할 수 있다.
- NONE: 생성자를 만들지 않는다. 즉, @NoArgsConstructor의 기능을 끄는 것이라고 생각하면 된다.
force
final 필드가 선언된 경우 컴파일 타임에 기본값을 0, false 또는 null으로 강제 초기화한다.
강제다 보니... 주의해서 사용해야 한다.
@NoArgsConstructor(force = true)
onConstructor
생성자에 다른 어노테이션을 추가할 때 사용한다.
@RequiredArgsConstructor(onConstructor = @__({@Inject}))
이 기능을 사용하면 컴파일 단계에서 다음과 같이 코드가 생성된다.
@Service
public class TestService {
private final UserService userService;
@Inject
public TestService(UserService userService) {
this.userService = userService;
}
}
일반적으로 Java에서 생성자 자체에는 어노테이션을 붙일 수 있긴 한데, 파라미터에는 붙일 수 없다.
Lombok은 이 문제를 해결하기 위해 @__를 사용해서 "이 어노테이션을 생성자 본문이 아니라 다른 위치에 붙여줘"라고 지시하는 역할을 한다.
2. @RequiredArgsConstructor
final 또는 @NotNull이 붙은 필수 필드만을 파라미터로 받는 생성자를 생성한다.
보통 의존성 주입(DI)할 때 final 필드를 초기화하는 용도로 많이 사용한다.
세부 옵션으로는 access, onConstructor, staticName 옵션을 가질 수 있다.
staticName
기존 생성자의 접근 제어자를 private으로 변경하고 정적 팩토리 메서드를 새로 생성해 준다.
보통 코드를 더 명확하게 만들고 싶을 때 사용한다.
@RequiredArgsConstructor(staticName = "of")
이 기능을 사용하면 컴파일 단계에서 다음과 같이 코드가 생성된다.
@Entity
public class User {
@Id @GeneratedValue
private Long id;
@Column @NotNull
private String name;
private User(String name) {
this.name = name;
}
// ID 없이 name 만으로 User 객체를 생성하는 정적 팩토리 메서드
public static User of(String name) {
return new User(name);
}
}
3. @AllArgsConstructor
모든 필드를 파라미터로 받는 생성자를 생성한다.
테스트 코드나 빌더 패턴과 함께 사용할 때 편리하다.
@RequiredArgsConstructor와 같이, access, onConstructor, staticName 옵션을 사용할 수 있다.
🙆♀️ JPA에서 활용하기
JPA 엔티티 클래스에서는 @NoArgsConstructor와 @AllArgsConstructor를 함께 사용하는 것이 가장 일반적이다.
import javax.persistence.Entity;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.Getter;
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED) // JPA를 위한 기본 생성자
@AllArgsConstructor // 테스트 등을 위한 전체 필드 생성자
public class User {
@Id @GeneratedValue
private Long id;
private String name;
// ...
}