java - LombokBuilder و JPA منشئ افتراضي




spring spring-data-jpa (4)

إذا كانت التعليقات التوضيحية lombok.Tolerate على المُنشئ و javax.validation.constrict.NotNull في بعض الممتلكات تُستخدم في نفس الوقت ، فسوف تقوم sonarqube بوضع علامة عليها كخطأ فادح: يتم وضع علامة على الملكية "javax.validation.constrict.NotNull" مهيأ في هذا المنشئ.

إذا كان المشروع يستخدم SpringData مع JPA ، فيمكن حلها باستخدام org.springframework.data.annotation.PersistenceConstructor (شرح الربيع ، وليس JPA!)

بعد ذلك ، بالاشتراك مع لومبوك ، ستكون التعليقات التوضيحية كما يلي:

@RequiredArgsConstructor(onConstructor = @__(@PersistenceConstructor))

تحتاج إلى إضافة منشئ لومبوك:

@Builder
@AllArgsConstructor

أنا أستخدم مشروع Lombok مع Spring Data JPA. هل هناك أي طريقة للاتصال @Builder مع @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


يبدو أن ترتيب التعليقات التوضيحية مهم هنا ، باستخدام نفس التعليقات التوضيحية ، لكن مع وجود أوامر مختلفة ، يمكنك تشغيل التعليمات البرمجية أم لا.

هنا مثال غير عملي:

@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 في الموضع العلوي ، وفي هذه الحالة واجهت هذا الخطأ لأنني أردت فرز التعليقات التوضيحية أبجديًا.


@NoArgsConstructor استخدام @NoArgsConstructor و @AllArgsContructor حل مشكلة وجود مُنشئ افتراضي مع @Builder .

على سبيل المثال

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

هذا لأن @Builder يتطلب كل مُنشئ الوسيطة وتحديد مُنشئ افتراضي فقط سيؤدي إلى مشكلة.

إليكم التوضيح التالي: https://github.com/rzwitserloot/lombok/issues/1389#issuecomment-369404719


محدث

استنادًا إلى التعليقات answer John ، قمت بتحديث الإجابة ، ولم أعد أستخدم @Tolerate أو @Data ، وبدلاً من ذلك ، نقوم بإنشاء وحدات وصول ومشغلات عبر @Getter و @Setter ، وإنشاء المنشئ الافتراضي عبر @NoArgsConstructor ، وأخيراً نقوم بإنشاء جميع الحجج مُنشئ يتطلب البناء من خلال @AllArgsConstructor .

نظرًا لأنك ترغب في استخدام نمط الباني ، أتصور أنك تريد تقييد رؤية المنشئ وطرق التحويل. ولتحقيق ذلك ، قمنا بتعيين إمكانية الرؤية @NoArgsConstructor package private خلال سمة access على التعليقات التوضيحية @AllArgsConstructor و @AllArgsConstructor value على تعليق توضيحي @Setter .

مهم

تذكر أن toString بشكل صحيح toString ، equals ، و hashCode . انظر الوظائف التالية بواسطة فلاد Mihalcea للحصول على التفاصيل:

package com..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 يجعل @Data تم @Data public ، وتطبيق @Setter(value = AccessLevel.PROTECTED) على الحقول التي تجعلهم protected .

تذكر أن toString بشكل صحيح toString ، equals ، و hashCode . انظر الوظائف التالية بواسطة فلاد Mihalcea للحصول على التفاصيل:

package lombok.javac.handlers.;

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