JPA에서 Lombok 사용시 주의할 점

dev-well-being·2023년 5월 19일
2
post-thumbnail
post-custom-banner

Lombok은 java 객체에서 getter, setter, toString, constructor 등 field별로 선언해줘야하는 메소드를 빌드과정에서 자동으로 생성해주는 라이브러리이다.

특히 DTO, VO 를 생성할 때 Lombok은 개발생산성과 번거로운 단순 반복 작업을 수월하게 해주는 고마운 존재이다.

JPA에서 Entity를 생성할 때도 Lombok을 많이들 사용할 것이다. 하지만 JPA에서 Lombok을 사용할 때는 주의사항이 몇 가지 있다고 한다. 아래 사이트는 JPA와 Lombok에 주의사항을 정리한 사이트다.

Lombok and JPA: What Could Go Wrong?

Broken HashSets (and HashMaps)

우리는 JPA Entity에서 종종 @EqualsAndHashCode, @Data annotation을 사용한다. JPA 엔티티에서 Equals()/hashCode() 구현은 민감한 주제다.

For example, let’s create a test entity:

@Entity
@EqualsAndHashCode
public class TestEntity {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(nullable = false)
   private Long id;
   
}

And execute the following code:

TestEntity testEntity = new TestEntity();
Set<TestEntity> set = new HashSet<>();

set.add(testEntity);
testEntityRepository.save(testEntity);

Assert.isTrue(set.contains(testEntity), "Entity not found in the set");

위 코드에서 마지막은 실패를 한다. @EqualsAndHashCode 디롬복을 해보면 아래와 같은 결과를 얻는다.

public int hashCode() {
   final int PRIME = 59;
   int result = 1;
   final Object $id = this.getId();
   result = result * PRIME + ($id == null ? 43 : $id.hashCode());
   return result;
}

jpa를 통해 저장을 하면 Id가 생성되면서 hashcode가 변경된다. 그래서 HashSet에 저장된 객체는 별도의 것으로 인지하게 된다.

Accidentally Loading Lazy Attributes

위에서 언급했듯이 @EqualsAndHashCode는 기본적으로 모든 객체 필드를 포함한다. 이는 @ToString도 마찬가지.

equals()/hashCode()/toString() 메소드는 객체의 모든 필드에서 호출한다. 이로 인해 JPA 엔티티에 원치 않는 부작용이 발생할 수 있다. 그것은 Lazy Attributes 로드하는 것.

예를 들면, hashCode() 메소드를 호출하면 @OneToMany에 lazy로 설정한 모두 엔티티들을 가져오게 된다. 만약 외부 트랙잭션에서 발생한다면 LazyInitializationException이 발생할 수 있다.

@ToString도 사용하려면 lazy로 지정한 필드는 제외시켜야 한다. lazy 필드에는 @ToString.Exclude 선언한다. 또는 클래스에 @ToString(onlyExplicitlyIncluded = true) 사용해거나 lazy가 아닌 필드에는 @ToString.Include를 사용한다.

Missing No-Argument Constructor

JPA 가이드에 따르면, 모든 엔티티 클래스는 public 또는 protected no-argument constructor가 요구된다. @AllArgsConstructor와 @Builder는 컴파일러가 기본 Constructor를 생성하지 않는다.

따라서 항상 @NoArgsConstructor 또는 인수가 없는 명시적 생성자와 함께 사용해야 한다.

Conclusion

JPA와 Lombok을 작업할 때 다음 규칙을 기억하자:

  • JPA Entity에는 @EqualsAndHashCode and @Data을 사용하지 말자.
  • @ToString을 사용할 때는 lazy field는 제외하자.
  • @Builder 또는 @AllArgsConstructor 사용할 때는 @NoArgsConstructor와 함께 사용하자.
profile
안녕하세요!! 좋은 개발 문화를 위해 노력하는 dev-well-being 입니다.
post-custom-banner

0개의 댓글