Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using id field in @AllArgsConstructor while using Spring JPA correct?

Using spring-boot and JPA I have an Entity I want to use lombok to reduce boilerplate code. However in my entity there is the id field. Shall I put it in the constructor arguments with @AllArgsConstructor or shall I eliminate it from theargument list (somehow, how?) due to being auto-generated with the @id and @GeneratedValue annotations?

code:

@Entity
@NoArgsConstructor // JPA requires empty constructor
@AllArgsConstructor // ? is id in constuctor needed?

@Getter
@Setter
@ToString(exclude = {"room", "customer"})
public class Reservation {

    @Id
    @GeneratedValue
    private long id;

    private Room room;
    private Customer customer;
    private Date dateFrom;
    private Date dateTo;    
}
like image 949
mCs Avatar asked Feb 14 '18 10:02

mCs


People also ask

Can we use @NoArgsConstructor and @AllArgsConstructor together?

But if you add a constructor with parameters (or @AllArgsConstructor ), then you'll need to add a no args constructor (or @NoArgsConstructor ) as well, for JPA/Hibernate to work.

When would you use a no arg constructor?

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.

Why do we use @AllArgsConstructor?

The @AllArgsConstructor annotation generates a constructor with one parameter for every field in the class. Fields that are annotated with @NonNull result in null checks with the corresponding parameters in the constructor. The annotation won't generate a parameter for the static and initialized final fields.

Why do we use @entity in spring boot?

The @Entity annotation specifies that the class is an entity and is mapped to a database table. The @Table annotation specifies the name of the database table to be used for mapping.


2 Answers

For your question in code:

@AllArgsConstructor // ? is id in constuctor needed?

No it is not needed. Furthermore, for your question in the title:

Is using id field in @AllArgsConstructor while using Spring JPA correct?

Field id it is not recommended to be exposed to any constructor or setter unless there is a very good reason for that. Field id should be manipulated only by JPA implementation.

Note that this expose happens also when you declare @Setter on Reservation class level.

This can be avoided to remove annotation from class level and annotate each field to expose but easier way is to use inheritance.

You can create a base class like:

@Entity
@Getter
// Choose your inheritance strategy:
//@Inheritance(strategy=InheritanceType.JOINED)
//@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class BaseEntity {
    @Id
    @GeneratedValue
    private Long id;
}

Note that it does not have setter for field id. Extend above class like:

@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString(exclude = {"room", "customer"})
public class Reservation extends BaseEntity {
    private Room room;
    private Customer customer;
    private Date dateFrom;
    private Date dateTo;    
}

and the constructors & setters will be the following:

Reservation r1 = new Reservation();
Reservation r2 = new Reservation(room, customer, dateFrom, dateTo);

r1.setRoom(room);
r1.setCustomer(customer);
r1.setDateFrom(dateFrom);
r1.setDateTo(dateTo);

and there is no way - other that reflection that JPA uses - to set the field id.

I do not know how spring-data-jpa exactly does setting the id but as there is a keyword JPA and tag jpa I assumes this is a JPA thing and that setter for field id is not actually needed at all.

like image 104
pirho Avatar answered Oct 18 '22 22:10

pirho


A comment for the Lombok part: There is no way to exclude field from the @AllArgsConstructor (without using inheritance). For a limited constructor, you can only use @RequiredArgsConstructor, but this will generally not help you for JPA entities.

like image 35
Michael Piefel Avatar answered Oct 18 '22 21:10

Michael Piefel