Lombok @Builder 및 JPA 기본 생성자
SpringData JPA와 함께 Lombok 프로젝트를 사용하고 있습니다. Lombok @Builder
을 JPA 기본 생성자와 연결하는 방법이 있습니까?
암호:
@Entity
@Builder
class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
}
내가 아는 한 JPA에는 @Builder
주석 으로 재정의되는 기본 생성자가 필요합니다 . 이에 대한 해결 방법이 있습니까?
이 코드는 오류를 제공합니다. org.hibernate.InstantiationException: No default constructor for entity: : app.domain.model.Person
업데이트 됨
피드백와 요한을 바탕으로 대답 나는 더 이상 사용에 대한 답변을 업데이트 한 @Tolerate
나 @Data
대신 우리는을 통해 접근 및 뮤 테이터를 작성 @Getter
하고 @Setter
,를 통해 기본 생성자를 생성 @NoArgsConstructor
하고, 마지막으로 우리는 빌더를 통해 필요로하는 모든 인수 생성자를 만듭니다 @AllArgsConstructor
.
빌더 패턴을 사용하고 싶기 때문에 생성자와 뮤 테이터 메소드의 가시성을 제한하고 싶다고 생각합니다. 이를 달성하기 위해 및 주석의 속성 과 주석 package private
의 access
속성 을 통해 가시성을로 설정합니다 .@NoArgsConstructor
@AllArgsConstructor
value
@Setter
중대한
제대로 대체 할 기억 toString
, equals
그리고 hashCode
. 자세한 내용은 Vlad Mihalcea의 다음 게시물을 참조하십시오.
- 구현하는 가장 좋은 방법은 jpa 및 최대 절전 모드를 사용하여 해시 코드 및 문자열과 같음
- jpa 엔터티 식별자를 사용하여 같음 및 해시 코드를 구현하는 방법
- 최대 절전 모드 사실 동일 및 해시 코드
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
주석 생성 된 세터하게 public
적용 @Setter(value = AccessLevel.PROTECTED)
분야로하는 그들을합니다 protected
.
제대로 대체 할 기억 toString
, equals
그리고 hashCode
. 자세한 내용은 Vlad Mihalcea의 다음 게시물을 참조하십시오.
- 구현하는 가장 좋은 방법은 jpa 및 최대 절전 모드를 사용하여 해시 코드 및 문자열과 같음
- jpa 엔터티 식별자를 사용하여 같음 및 해시 코드를 구현하는 방법
- 최대 절전 모드 사실 동일 및 해시 코드
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());
}
}
@Data @Builder @NoArgsConstructor @AllArgsConstructor
클래스 정의에 결합하여 명시 적으로 해결할 수도 있습니다 .
여기에서는 주석 순서가 중요한 것 같습니다. 동일한 주석을 사용하지만 다른 순서를 사용하면 코드가 작동하거나 작동하지 않을 수 있습니다.
다음은 작동하지 않는 예입니다.
@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;
}
So be sure to have the @Builder annotation at the very top position, in my case I encountered this error because I wanted to sort annotations alphabetically.
If the annotations lombok.Tolerate on constructor and javax.validation.constraints.NotNull on some property are used at the same time, sonarqube will mark it as a critical error: PROPERTY is marked "javax.validation.constraints.NotNull" but is not initialized in this constructor.
If the project uses SpringData with JPA, it can be solved using org.springframework.data.annotation.PersistenceConstructor (Spring annotation, not JPA!)
Then, in combination with Lombok, annotations will be like this:
@RequiredArgsConstructor(onConstructor = @__(@PersistenceConstructor))
For Lombok builder you also need to add:
@Builder
@AllArgsConstructor
Using @NoArgsConstructor
and @AllArgsContructor
will help solve the issue of having a default constructor with @Builder
.
e.g
@Entity
@Builder
@NoArgsConstructor
@AllArgsContructor
class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
}
This is because @Builder
requires all argument constructor and specifying only a default constructor will cause an issue.
Here is nore explaination: https://github.com/rzwitserloot/lombok/issues/1389#issuecomment-369404719
ReferenceURL : https://stackoverflow.com/questions/34241718/lombok-builder-and-jpa-default-constructor
'developer tip' 카테고리의 다른 글
C ++ 11에서 N 요소 constexpr 배열 만들기 (0) | 2020.12.15 |
---|---|
셀레늄 드라이버에 대한 사용자 에이전트 변경 (0) | 2020.12.15 |
Lambda 함수 내에서 직접 Thread # sleep ()을 호출 할 수없는 이유는 무엇입니까? (0) | 2020.12.15 |
오류 : 메소드의 서명 없음 : com.crashlytics.tools.gradle.CrashlyticsPlugin.findObfuscationTransformTask () (0) | 2020.12.15 |
$ {var} 매개 변수 확장 표현식이 bash에 중첩 될 수 있습니까? (0) | 2020.12.15 |