Lombok @Builder和JPA Default构造函数 [英] Lombok @Builder and JPA Default constructor

查看:1625
本文介绍了Lombok @Builder和JPA Default构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用项目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 @Setterannotation.

重要

请记住正确覆盖 toString 等于 hashCode
有关详细信息,请参阅Vlad Mihalcea的以下帖子:

Remember to properly override toString, equals, and hashCode. See the following posts by Vlad Mihalcea for details:

  • 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:

  • 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆