当前位置: 首页 > 知识库问答 >
问题:

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

凌朗
2023-03-14

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

代码:

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

据我所知,JPA需要默认构造函数,该构造函数由@Builder注释覆盖。有什么解决办法吗?

这段代码给我错误:< code > org . hibernate . instantiation exception:entity::app . domain . model . person没有默认构造函数

共有3个答案

寇宏义
2023-03-14

似乎注释顺序在这里很重要,使用相同的注释,但顺序不同,您可以让代码工作,也可以不工作。

这是一个不起作用的示例:

@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注释放在最顶部的位置,在我的例子中,我遇到了这个错误,因为我想按字母顺序对注释进行排序。

澹台华晖
2023-03-14

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

容修贤
2023-03-14

已更新

根据反馈和John的回答,我将答案更新为不再使用@T的@Data,取而代之的是我们通过@Getter@Setter创建访问器和突变器,通过@NoArgsCon结构函数创建默认构造函数,最后我们通过@AllArgsCon结构函数创建构建器需要的所有args构造函数。

由于您想使用构建器模式,我想您想限制构造函数和变形器方法的可见性。为了实现这一点,我们通过@NoArgsCon的@AllArgsCon的注解上的访问属性以及@Setter注解上的属性将可见性设置为包私有

重要的

记住要正确地覆盖< code>toString 、< code>equals和< code>hashCode。详情见Vlad Mihalcea的以下帖子:

  • 最好的实现方法是使用jpa和hibernate实现hashcode和tostring
  • 如何使用jpa实体标识符实现equals和hashcode
  • hibernate事实等于和哈希码
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());
    }
}

使用@T的旧版本@Data

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

既然您想使用构建器模式,我想您想控制setter方法的可见性。

@Data注释使生成的Setter公共,将 >应用于字段使其

记住要正确地覆盖< code>toString 、< code>equals和< code>hashCode。详情见Vlad Mihalcea的以下帖子:

  • 最好的实现方法是使用jpa和hibernate实现hashcode和tostring
  • 如何使用jpa实体标识符实现equals和hashcode
  • hibernate事实等于和哈希码
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项目与Spring Data JPA一起使用。有什么方法可以将Lombok 与JPA默认构造函数连接? 码: 据我所知,JPA需要默认的构造函数,该构造函数被注解覆盖。有什么解决方法吗? 这段代码给我错误: 问题答案: 更新 根据反馈和John的回答,我已更新了不再使用or的答案,而是通过和创建访问器和变量,通过创建默认构造函数via,最后我们创建了构建器通过via

  • 我使用默认构造函数从子类中设置recordId的值,最初没有使用lombok。最终我决定在这里使用构建器,但现在的问题是lombok构建器在内部覆盖了我的默认构建器,因此从未设置值。

  • 正如JPA所要求的,类应该有一个默认的(非参数)构造函数,以便在从数据库检索对象时实例化它们。 在Kotlin中,属性在主构造函数内声明非常方便,如下例所示: 但是当非arg构造函数被声明为次要构造函数时,它需要传递主构造函数的值,因此它们需要一些有效的值,如下所示: 如果属性具有比和更复杂的类型,并且它们是不可为空的,那么为它们提供值看起来是非常糟糕的,特别是当主构造函数和块中有很多代码,并且当

  • 我在Maven的Spring启动项目中使用Lombok。我的IDE是vscode 我尝试使用Lombok注释器创建这样的类: 它工作正常。但是,当我尝试切换到注释时,我遇到了一个错误: 我以为@Data注释应该为我构建构造函数。这是怎么回事?

  • 问题内容: 不知何故,在下面的Node类中,and变量在Node的所有实例之间共享。 有什么办法可以让我继续使用构造函数参数的默认值(在这种情况下为空列表),但要同时获取它们和拥有其自身的变量以及变量? 我正在使用python 3.1.2。 问题答案: 可变的默认参数通常不会执行您想要的操作。相反,请尝试以下操作:

  • 我正在使用Lombok的注释在我的类中创建一个超级构造函数。 我的抽象控制器类: 我的控制器实现类: 我的服务类别: 基本上,我希望Lombok在中创建一个类似的构造函数 我的应用程序无法启动,错误消息如下所示: MyAbstractControllerImpl中构造函数的参数0需要类型为“MyAbstractControllerImpl$MyAbstractControllerImpBuilde