Явный конструктор с использованием 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}
}