Явный конструктор, использующий 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());
}
Кроме того, оригинальный программист этого кода говорит, что он допускает, чтобы заголовок был "нулевым", но он явно создал конструктор, которому нужно значение для заголовка. Я что-то упустил или это немного противоречиво?
4 ответа
Посмотри на @NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor
,
Поведение конструктора @Data
как @RequiredArgsConstructor
:
@RequiredArgsConstructor генерирует конструктор с 1 параметром для каждого поля, которое требует специальной обработки. Все конечные поля получают параметр, а также любые поля, помеченные как @NonNull, которые не инициализированы там, где они объявлены.
Учитывая, что ни одно из ваших полей не final
или же @NonNull
это приведет к появлению конструктора без аргументов. Однако это не самый выразительный способ добиться такого поведения.
В этом случае вы, вероятно, захотите @NoArgsConstructor
(опционально в сочетании с @AllArgsConstructor
), чтобы четко сообщить предполагаемое поведение, как также указано в документации:
Для некоторых конструкций Java, таких как hibernate и интерфейс Service Provider, требуется конструктор без аргументов. Эта аннотация полезна прежде всего в сочетании с @Data или одним из других конструкторов, генерирующих аннотации.
Если вы используете @Data с полем @NonNull и по-прежнему хотите использовать конструктор noargs, вы можете попробовать добавить все три аннотации вместе
@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor
Очевидно старая ошибка intelliJ, которую я повторил в Eclipse Kepler и lombok v0.11.4
Этот бит противоречив, вы правы. Я не использовал Lombok раньше, но с hibernate, если вы хотите иметь возможность создавать bean-компонент и сохранять его, вам нужен конструктор по умолчанию, как указано выше, насколько я знал. Он использует Constructor.newInstance() для создания новых объектов.
Вот некоторая документация гибернации, которая идет в более подробно.
@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}
}