I'm rewriting some messy code that manages a database, and saw that the original programmer created a class mapped to the database like so:
(I've removed unnecessary code that has no purpose in this question)
@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;
    }
}
I am still a beginner at Hibernate and using Lombok, but wouldn't this do the same thing and wouldn't Lombok automatically create the needed constructor for you?
@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());
}
Also, the original programmer of this code says he allows for the header to be 'null', yet he explicitly created a constructor that needs a value for header. Am I missing something or is this a bit contradictory?
With Lombok, it's possible to generate a constructor for either all class's fields (with @AllArgsConstructor) or all final class's fields (with @RequiredArgsConstructor). Moreover, if you still need an empty constructor, you can append an additional @NoArgsConstructor annotation.
It generates a constructor that initializes all the final fields, as well as all the non-final fields with no initializer that have been marked with @NonNull , in order to ensure that the field is never null.
@RequiredArgsConstructor generates a constructor with 1 parameter for each field that requires special handling. All non-initialized final fields get a parameter, as well as any fields that are marked as @NonNull that aren't initialized where they are declared.
Have a look at @NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor. 
The constructor behavior of @Data is like @RequiredArgsConstructor:
@RequiredArgsConstructor generates a constructor with 1 parameter for each field that requires special handling. All final fields get a parameter, as well as any fields that are marked as @NonNull that aren't initialized where they are declared.
Given that none of your fields are either final or @NonNull, this will result in a no-argument constructor. However, this is not the most expressive way to achieve this behavior.
What you'll probably want in this case is a @NoArgsConstructor (optionally combined with a @AllArgsConstructor), to clearly communicate the intended behavior, as is also indicated in the documentation:
Certain java constructs, such as hibernate and the Service Provider Interface require a no-args constructor. This annotation is useful primarily in combination with either @Data or one of the other constructor generating annotations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With