복붙노트

[SPRING] Lombok @Builder 및 JPA 기본 생성자

SPRING

Lombok @Builder 및 JPA 기본 생성자

저는 Spring Data JPA와 함께 Lombok 프로젝트를 사용하고 있습니다. Lombok @Builder를 JPA 기본 생성자와 연결할 수있는 방법이 있습니까?

암호:

@Entity 
@Builder
class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
}

내가 아는 한 JPA는 @Builder 주석에 의해 재정의되는 기본 생성자를 필요로합니다. 거기에 대한 해결 방법이 있습니까?

이 코드는 내게 오류가 발생합니다 : org.hibernate.InstantiationException : 엔티티에 대한 기본 생성자가 없습니다. : app.domain.model.Person

해결법

  1. ==============================

    1.업데이트 됨

    업데이트 됨

    피드백과 John의 대답에 따라 @Tolerate 또는 @Data를 사용하지 않고 @Getter 및 @Setter를 통해 접근 자 및 변형자를 만들고 @NoArgsConstructor를 통해 기본 생성자를 만들고 마지막으로 모든 args를 만듭니다 @AllArgsConstructor를 통해 빌더에 필요한 생성자.

    당신이 생성자 패턴을 사용하기를 원하기 때문에 생성자와 mutator 메소드의 가시성을 제한하고 싶다고 생각합니다. 이를 위해 우리는 @NoArgsConstructor 및 @AllArgsConstructor 주석의 access 속성과 @Setterannotation의 value 속성을 통해 package private에 대한 가시성을 설정합니다.

    중대한

    toString, equals 및 hashCode를 올바르게 재정의해야합니다. 자세한 내용은 Vlad Mihalcea의 다음 게시물을 참조하십시오.

    package com.stackoverflow.SO34299054;
    
    import static org.junit.Assert.*;
    
    import java.util.Random;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    import org.junit.Test;
    
    import lombok.AccessLevel;
    import lombok.AllArgsConstructor;
    import lombok.Builder;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    
    @SuppressWarnings("javadoc")
    public class Answer {
    
        @Entity
        @Builder(toBuilder = true)
        @AllArgsConstructor(access = AccessLevel.PACKAGE)
        @NoArgsConstructor(access = AccessLevel.PACKAGE)
        @Setter(value = AccessLevel.PACKAGE)
        @Getter
        public static class Person {
    
            @Id
            @GeneratedValue(strategy = GenerationType.AUTO)
            private Long id;
    
            /*
             * IMPORTANT:
             * Set toString, equals, and hashCode as described in these
             * documents:
             * - https://vladmihalcea.com/the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate/
             * - https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/
             * - https://vladmihalcea.com/hibernate-facts-equals-and-hashcode/
             */
        }
    
        /**
         * Test person builder.
         */
        @Test
        public void testPersonBuilder() {
    
            final Long expectedId = new Random().nextLong();
            final Person fromBuilder = Person.builder()
                .id(expectedId)
                .build();
            assertEquals(expectedId, fromBuilder.getId());
    
        }
    
        /**
         * Test person constructor.
         */
        @Test
        public void testPersonConstructor() {
    
            final Long expectedId = new Random().nextLong();
            final Person fromNoArgConstructor = new Person();
            fromNoArgConstructor.setId(expectedId);
            assertEquals(expectedId, fromNoArgConstructor.getId());
        }
    }
    

    @Tolerate 및 @Data를 사용하는 이전 버전 :

    @Tolerate를 사용하면 noarg 생성자를 추가 할 수 있습니다.

    빌더 패턴을 사용하기를 원하기 때문에 setter 메소드의 가시성을 제어하고 싶다고 생각합니다.

    @Data 주석은 생성 된 setter를 public으로 만들고 필드에 @Setter (value = AccessLevel.PROTECTED)를 적용하여 보호합니다.

    toString, equals 및 hashCode를 올바르게 재정의해야합니다. 자세한 내용은 Vlad Mihalcea의 다음 게시물을 참조하십시오.

    package lombok.javac.handlers.stackoverflow;
    
    import static org.junit.Assert.*;
    
    import java.util.Random;
    
    import javax.persistence.GenerationType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    
    import lombok.AccessLevel;
    import lombok.Builder;
    import lombok.Data;
    import lombok.Setter;
    import lombok.experimental.Tolerate;
    
    import org.junit.Test;
    
    public class So34241718 {
    
        @Builder
        @Data
        public static class Person {
    
            @Id
            @GeneratedValue(strategy = GenerationType.AUTO)
            @Setter(value = AccessLevel.PROTECTED)
            Long id;
    
            @Tolerate
            Person() {}
    
           /* IMPORTANT:
              Override toString, equals, and hashCode as described in these 
              documents:
              - https://vladmihalcea.com/the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate/
              - https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/
              - https://vladmihalcea.com/hibernate-facts-equals-and-hashcode/
              */
        }
    
        @Test
        public void testPersonBuilder() {
    
            Long expectedId = new Random().nextLong();
            final Person fromBuilder = Person.builder()
                .id(expectedId)
                .build();
            assertEquals(expectedId, fromBuilder.getId());
    
        }
    
        @Test
        public void testPersonConstructor() {
    
            Long expectedId = new Random().nextLong();
            final Person fromNoArgConstructor = new Person();
            fromNoArgConstructor .setId(expectedId);
            assertEquals(expectedId, fromNoArgConstructor.getId());
        }
    }
    
  2. ==============================

    2.@Builder @NoArgsConstructor @AllArgsConstructor를 클래스 정의에 결합하여 명시 적으로 해결할 수도 있습니다.

    @Builder @NoArgsConstructor @AllArgsConstructor를 클래스 정의에 결합하여 명시 적으로 해결할 수도 있습니다.

  3. ==============================

    3.일부 속성의 lombok.Tolerate 및 javax.validation.constraints.NotNull이 동시에 사용되는 경우 sonarqube는이 속성을 중요한 오류로 표시합니다. PROPERTY는 "javax.validation.constraints.NotNull"으로 표시되었지만 표시되지 않습니다. 이 생성자으로 초기화됩니다.

    일부 속성의 lombok.Tolerate 및 javax.validation.constraints.NotNull이 동시에 사용되는 경우 sonarqube는이 속성을 중요한 오류로 표시합니다. PROPERTY는 "javax.validation.constraints.NotNull"으로 표시되었지만 표시되지 않습니다. 이 생성자으로 초기화됩니다.

    프로젝트가 JPA와 함께 SpringData를 사용한다면, org.springframework.data.annotation.PersistenceConstructor (JPA가 아닌 Spring 주석)를 사용하여 해결할 수 있습니다.

    그런 다음 Lombok과 함께 주석을 다음과 같이 만듭니다.

    @RequiredArgsConstructor(onConstructor = @__(@PersistenceConstructor))
    

    롬복 빌더의 경우 다음을 추가해야합니다.

    @Builder
    @AllArgsConstructor
    
  4. ==============================

    4.어노테이션 순서는 여기에서 중요하며, 동일한 주석을 사용하지만 다른 주문을 사용하면 코드가 작동하는지 여부가 중요합니다.

    어노테이션 순서는 여기에서 중요하며, 동일한 주석을 사용하지만 다른 주문을 사용하면 코드가 작동하는지 여부가 중요합니다.

    다음은 작동하지 않는 예제입니다.

    @AllArgsConstructor
    @Builder
    @Data
    @Entity
    @EqualsAndHashCode
    @NoArgsConstructor
    @RequiredArgsConstructor
    @Table
    @ToString
    public class Person implements Serializable {
      private String name;
    }
    

    그리고 이것은 실제적인 예입니다 :

    @Builder
    @Data
    @Entity
    @EqualsAndHashCode
    @AllArgsConstructor
    @NoArgsConstructor
    @RequiredArgsConstructor
    @Table
    @ToString
    public class Person implements Serializable {
      private String name;
    }
    

    따라서 최상위 위치에 @Builder 주석이 있어야합니다. 필자는 주석을 사전 순으로 정렬하기 때문에이 오류가 발생했습니다.

  5. from https://stackoverflow.com/questions/34241718/lombok-builder-and-jpa-default-constructor by cc-by-sa and MIT license