Явный конструктор с использованием Lombok?

Я переписываю какой-то грязный код, который управляет базой данных, и увидел, что исходный программист создал класс, сопоставленный с базой данных следующим образом:

(я удалил ненужный код, который не имеет цели в этом вопросе)

@Entity
@Data
@EqualsAndHashCode(callSuper = false, of = { "accessionCode", "header", "date" })
@SuppressWarnings("PMD.UnusedPrivateField")
public class PDBEntry implements Serializable {
    @Id
    @NaturalId
    @NotEmpty
    @Length(max = 4)
    private String accessionCode;

    @NaturalId
    @NotEmpty
    private Date date;

    @NaturalId
    // We allow for the header to be 'null'
    private String header;

    private Boolean isValidDssp;

    @Temporal(TemporalType.TIMESTAMP)
    private Date lastUpdated = new Date(System.currentTimeMillis());

    protected PDBEntry(){}

    public PDBEntry(String accessionCode, String header, Date date){
        this.accessionCode = accessionCode;
        this.header = header;
        this.date = date;
    }
}

Я все еще новичок в Hibernate и использую Lombok, но не будет ли это делать то же самое, и не будет ли Lombok автоматически создавать необходимый конструктор для вас?

@Entity
@Data
@SuppressWarnings("PMD.UnusedPrivateField")
public class PDBEntry implements Serializable {
    @Id
    @NaturalId
    @NotEmpty
    @NonNull
    @Length(max = 4)
    private String accessionCode;

    @NaturalId
    @NotEmpty
    @NonNull
    private Date date;

    @NaturalId
    // We allow for the header to be 'null'
    private String header;

    private Boolean isValidDssp;

    @Temporal(TemporalType.TIMESTAMP)
    private Date lastUpdated = new Date(System.currentTimeMillis());
}

Кроме того, исходный программист этого кода говорит, что он допускает, чтобы заголовок был "null", но он явно создал конструктор, которому требуется значение для заголовка. Я что-то пропустил или это немного противоречиво?

Ответы

Ответ 1

Посмотрите @NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor.

Поведение конструктора @Data похоже на @RequiredArgsConstructor:

@RequiredArgsConstructor генерирует конструктор с 1 параметром для каждого поле, которое требует специальной обработки. Все конечные поля получают параметр, так как а также любые поля, отмеченные как @NonNull, которые не инициализируются, где они объявлены.

Учитывая, что ни одно из ваших полей не является final или @NonNull, это приведет к конструктору без аргументов. Однако это не самый выразительный способ достижения такого поведения.

В этом случае вам, возможно, понадобится @NoArgsConstructor (необязательно в сочетании с @AllArgsConstructor), чтобы четко сообщать о предполагаемом поведении, как это указано в документации:

Некоторые java-конструкции, такие как спящий режим и поставщик услуг Интерфейс требует no-args конструктор. Эта аннотация полезна прежде всего в сочетании с @Data или один из другого конструктора генерации аннотаций.

Ответ 2

Этот бит противоречив, вы правы. Я раньше не использовал Lombok, но с hibernate, если вы хотите создать bean и сохраняете, что вам нужен конструктор по умолчанию, как указано выше, насколько мне известно. Он использует Constructor.newInstance() для создания новых объектов.

Ниже приведена небольшая документация с гибернацией.

Hibernate Documentation

Ответ 3

Если вы используете @Data с полем @NonNull и все еще хотите конструктор noargs, вы можете попытаться добавить все 3 аннотации вместе

@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor

По-видимому, старая ошибка intelliJ, которую я реплицировал в Eclipse Kepler и lombok v0.11.4

Ответ 4

@NoArgsConstructor, 
@RequiredArgsConstructor, 
@AllArgsConstructor

Генерируйте конструкторы, которые не принимают аргументов, один аргумент в конечном/ненулевом поле или один аргумент для каждого поля. Читать этот ломбок-проект

@Data
@RequiredArgsConstructor /*Duplicate method Someclass() in type Someclass*/
@NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)  /*Duplicate method Someclass() in type Someclass*/
@Entity
public class Someclass {      
    @Id
    private  String id;
    private  String name;
    private  Type type; 

    public static enum Type { X , Y, Z}
}

Исправлено, делая переменные-члены окончательными

@Data
@RequiredArgsConstructor 
@NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)
@Entity
public class Someclass {

    @Id
    private final String id;
    private final String name;
    private final Type type; 
    public static enum Type { X , Y, Z}
}