Construtor explícito usando Lombok?
Pergunta
Estou reescrevendo um código confuso que gerencia um banco de dados e vi que o programador original criou uma classe mapeada para o banco de dados assim:
(Removi código desnecessário que não tem propósito nesta questão)
@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;
}
}
Ainda sou iniciante no Hibernate e uso o Lombok, mas isso não faria a mesma coisa e o Lombok não criaria automaticamente o construtor necessário para você?
@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());
}
Além disso, o programador original deste código diz que permite que o cabeçalho seja 'nulo', mas criou explicitamente um construtor que precisa de um valor para o cabeçalho.Estou faltando alguma coisa ou isso é um pouco contraditório?
Solução
Dê uma olhada em @NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor
.
O comportamento do construtor de @Data
é como @RequiredArgsConstructor
:
O @ReQuiredargSconstructor gera um construtor com 1 parâmetro para cada campo que requer manuseio especial. Todos os campos finais obtêm um parâmetro, bem como quaisquer campos marcados como @Nonnull que não são inicializados onde são declarados.
Dado que nenhum dos seus campos é final
ou @NonNull
, isso resultará em um construtor sem argumento. No entanto, essa não é a maneira mais expressiva de alcançar esse comportamento.
O que você provavelmente vai querer neste caso é um @NoArgsConstructor
(opcionalmente combinado com um @AllArgsConstructor
), para comunicar claramente o comportamento pretendido, como também é indicado na documentação:
Certas construções de Java, como o hibernato e a interface do provedor de serviços, requerem um construtor de não-ARGs. Esta anotação é útil principalmente em combinação com as anotações @Data ou de um outro construtor que gera.
Outras dicas
Essa parte é contraditória, você está certo. Eu não usei o Lombok antes, mas com o Hibernate, se você quiser poder criar um feijão e persistir, precisa do construtor padrão, conforme dado acima, até agora eu estava ciente. Ele usa o construtor.NewInstance () para instanciar novos objetos.
Aqui está uma documentação de hibernação que entra em mais detalhes.
Se você estiver usando @data com um campo @Nonnull e ainda quiser um constitutor de noargs, você pode tentar adicionar todas as 3 anotações juntas
@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor
Aparentemente, um velho Intellij Bug, que eu repliquei no Eclipse Kepler e Lombok v0.11.4
@NoArgsConstructor,
@RequiredArgsConstructor,
@AllArgsConstructor
Gere construtores que não aceitam argumentos, um argumento por campo final/não nulo ou um argumento para cada campo.Leia isso projeto lombok
@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}
}
Corrigido tornando as variáveis de membro finais
@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}
}