龙目岛@Builder和 JPA 默认构造函数

2022-08-31 10:32:21

我正在将龙目岛项目与Spring Data JPA一起使用。有没有办法将龙目岛与JPA默认构造函数连接起来?@Builder

法典:

@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


答案 1

更新

根据反馈和John的答案,我更新了答案,不再使用@Tolerate@Data而是我们通过@Getter@Setter创建访问器和赋值器,通过@NoArgsConstructor创建默认构造函数,最后我们通过@AllArgsConstructor创建构建器所需的所有参数构造函数。

由于您希望使用构建器模式,因此我想您希望限制构造函数和赋值函数方法的可见性。为此,我们将可见性设置为通过 和 注释上的属性和注释上的属性。package privateaccess@NoArgsConstructor@AllArgsConstructorvalue@Setter

重要

请记住正确覆盖 、 和 。有关详细信息,请参阅Vlad Mihalcea的以下帖子:toStringequalshashCode

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的旧版本:

使用 worked 允许添加 noarg 构造函数。@Tolerate

由于您要使用生成器模式,因此我想您希望控制 setter 方法的可见性。

注释使生成的 setter,应用于字段使它们 。@Datapublic@Setter(value = AccessLevel.PROTECTED)protected

请记住正确覆盖 、 和 。有关详细信息,请参阅Vlad Mihalcea的以下帖子:toStringequalshashCode

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

您还可以通过在类定义上组合来显式解决它。@Data @Builder @NoArgsConstructor @AllArgsConstructor


推荐