Lombok @Builder和JPA Default构造函数 [英] Lombok @Builder and JPA Default constructor
问题描述
我正在使用项目Lombok和Spring Data JPA。
有没有办法将Lombok @Builder
与JPA默认构造函数连接?
I'm using project Lombok together with Spring Data JPA.
Is there any way to connect Lombok @Builder
with JPA default constructor?
代码:
@Entity
@Builder
class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
}
据我所知JPA需要默认构造函数,该构造函数被<$ c覆盖$ c> @Builder 注释。有什么解决方法吗?
As far as I know JPA needs default constructor which is overriden by @Builder
annotation. Is there any workaround for that?
这段代码给了我错误:
org.hibernate.InstantiationException:没有实体的默认构造函数: :app.domain.model.Person
This code gives me error:
org.hibernate.InstantiationException: No default constructor for entity: : app.domain.model.Person
推荐答案
已更新
根据反馈和John的回答我已更新答案不再使用 @Tolerate
或 @Data
而是通过 @Getter
和 @Setter
,通过 @NoArgsConstructor
创建默认构造函数,最后我们通过 @AllArgsConstructor
创建构建器所需的所有args构造函数。
Based on the feedback and John's answer I have updated the answer to no longer use @Tolerate
or @Data
and instead we create accessors and mutators via @Getter
and @Setter
, create the default constructor via @NoArgsConstructor
, and finally we create the all args constructor that the builder requires via @AllArgsConstructor
.
因为你想要使用构建器模式我想你想要限制构造函数和mutators方法的可见性。
为实现此目的,我们通过<$ c $上的 access
属性将可见性设置为 package private
c> @NoArgsConstructor 和 @AllArgsConstructor
注释以及<$ c上的值
属性$ c> @Setter 注释。
Since you want to use the builder pattern I imagine you want to restrict visibility of the constructor and mutators methods.
To achieve this we set the visibility to package private
via the access
attribute on the @NoArgsConstructor
and @AllArgsConstructor
annotations and the value
attribute on the @Setter
annotation.
重要
请记住正确覆盖 toString
,等于
, hashCode
。
有关详细信息,请参阅Vlad Mihalcea的以下帖子:
Remember to properly override toString
, equals
, and hashCode
.
See the following posts by Vlad Mihalcea for details:
- best-way-to-implement-equals-hashcode-and-tostring- with-jpa-and-hibernate
- how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier
- hibernate-facts-equals-and-hashcode
- the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate
- how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier
- hibernate-facts-equals-and-hashcode
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
:
Old Version using @Tolerate
and @Data
:
使用 @Tolerate
允许添加noarg构造函数。
Using @Tolerate
worked to allow adding a noarg constructor.
因为你想使用构建器模式我想你想要控制可见性setter方法。
Since you want to use the builder pattern I imagine you want to control visibility of the setter methods.
@Data
注释使生成的setter public
,将 @Setter(value = AccessLevel.PROTECTED)
应用于字段使它们 protected
。
The @Data
annotation makes the generated setters public
, applying @Setter(value = AccessLevel.PROTECTED)
to the fields makes them protected
.
请记住正确覆盖 toString
,等于
,以及的hashCode
。
有关详细信息,请参阅Vlad Mihalcea的以下帖子:
Remember to properly override toString
, equals
, and hashCode
.
See the following posts by Vlad Mihalcea for details:
- best-way-to-implement-equals-hashcode-and-tostring- with-jpa-and-hibernate
- how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier
- hibernate-facts-equals-and-hashcode
- the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate
- how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier
- hibernate-facts-equals-and-hashcode
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());
}
}
这篇关于Lombok @Builder和JPA Default构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!