본문 바로가기
Back-end/Spring Boot

[에러해결 SpringBoot] Lombok @DATA 컴파일 에러

by whatamigonnabe 2022. 7. 3.

문제상황

Lombok에서 @DATA 어노테이션을 사용한 클래스에서 아래의 에러가 발생했습니다.

@NoArgsConstructor
@AllArgsConstructor
@Data
public class WishlistEntity extends MemoryDbEntity {
    private String title;
    private String category;
    private String address;
    private String readAddress;
    private String homePageLink;
    private String imageLink;
    private boolean isVisit;
    private int visitCount;
    private LocalDateTime lastVisitDate;

}
더보기

Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.

 

문제원인

우선 DATA annotation이 뭔지 제대로 알지 못하고 사용한 것이 문제였습니다...

 

@DATA는 constructor, getter, setter, toString, equals, hashcode 등 메서드를 자동으로 생성합니다.

이 중 equals와 hashcode는 해당 클래스가 다른 클래스를 상속했더라도, 자신의 멤버만으로 equals와 hashcode를 오버라이딩합니다.

그래서 위에서 상속한 클래스가 @DATA를 사용했기 때문에, 따로 @EqualsAndHashCode어노테이션을 사용해서 super class의 멤버도 포함해서 equals과 hashcode를 오버라이딩 할지 명시하지 않았기 때문에 에러가 발생한 것입니다.

 

해결방법

따라서, @DATA의 디폴트처럼 포함하지 않으려면 위의 에러문구처럼 @EqualsAndHashCode(callSuper=false)를 더하면 됩니다.

저의 케이스는 super class가 id 멤버를 가지고 있기 때문에 calssSuper=true를 적용해야할 것 같습니다. 하지만, identity식별 기능이 있는 다른 클래스가 있어 의미가 없을 것 같긴합니다.

 

추가로 멤버들 중 일부만을 가지고 동일성을 식별하고 싶은 경우 두 가지 방법을 이용할 수 있습니다.

1. 일부만 제외하기

@EqualsAndHashCode.Exclude을 이용하여 포함하지 않을 멤버를 명시합니다.

@Data
public class WishlistEntity extends MemoryDbEntity {
    private String title;
    private String category;
    private String address;
    @EqualsAndHashCode.Exclude
    private String readAddress;
    @EqualsAndHashCode.Exclude
    private String homePageLink;
}

2. 일부만 포함하기

@Data
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class WishlistEntity extends MemoryDbEntity {
	@EqualsAndHashCode.Include
    private String title;
    @EqualsAndHashCode.Include
    private String category;
    @EqualsAndHashCode.Include
    private String address;
    private String readAddress;
    private String homePageLink;
}

 

또는 많은 블로그에서 아래와 같이 정리한 설명을 보았는데

별도로 구현하는 Value Object 가 없다면 위에 callSuper=false 있다면 위 링크를 보고 참조해서 구현하면 됩니다.

아마도 VO만 멤버 변수로 가지고 있다면, 그 자체로 동일성을 식별할 수 없기 때문인 것 같습니다.