1. ホーム
  2. java

[解決済み] Lombokの@BuilderとJPAのデフォルトコンストラクタ

2023-04-20 03:54:31

質問

Spring Data JPAと一緒にLombokプロジェクトを使っています。 LombokとSpring Data JPAを接続する方法はありますか? @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

どのように解決するのですか?

更新

フィードバックと John の 回答 を使用しないよう、回答を更新しました。 @Tolerate または @Data で、代わりにアクセッサとミューテータを @Getter@Setter で、デフォルトのコンストラクタを作成します。 @NoArgsConstructor そして最後に、ビルダーが要求するすべての引数のコンストラクタを @AllArgsConstructor .

ビルダーパターンを使用したいので、コンストラクタとミューテータのメソッドの可視性を制限したいのだと思います。 これを実現するために、可視性を package private を介して access 属性で @NoArgsConstructor@AllArgsConstructor アノテーションと value 属性は @Setter アノテーションを使用します。

重要な

を適切にオーバーライドすることを忘れないでください。 toString , equals そして hashCode . 詳しくはVlad Mihalcea氏による以下の投稿をご覧ください。

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コンストラクタを追加できるようになりました。

ビルダーパターンを使用したいので、セッターメソッドの可視性を制御したいのだと思います。

そのため @Data アノテーションは、生成されたセッターを public を適用します。 @Setter(value = AccessLevel.PROTECTED) を適用すると、フィールドは protected .

を適切にオーバーライドすることを忘れないでください。 toString , equals そして hashCode . 詳しくはVlad Mihalcea氏による以下の投稿をご覧ください。

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());
    }
}