使用 Spring JPA 时在 @AllArgsConstructor 中使用 id 字段是否正确?
Is using id field in @AllArgsConstructor while using Spring JPA correct?
使用 spring-boot
和 JPA 我有一个 Entity
我想使用 lombok 来减少样板代码。但是在我的实体中有 id
字段。我应该将它放在带有 @AllArgsConstructor
的构造函数参数中,还是应该将其从参数列表中删除(不知何故,如何?)因为它是使用 @id
和 @GeneratedValue
注释自动生成的?
代码:
@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;
}
在这种情况下 spring-data
使用 setter 来设置值,因此不需要 @AllArgsConstructor
。
对于您在代码中的问题:
@AllArgsConstructor // ? is id in constuctor needed?
不,不需要。另外,对于你标题中的问题:
Is using id field in @AllArgsConstructor while using Spring JPA correct?
字段 id
不建议将其暴露给任何构造函数或 setter 除非有充分的理由。字段 id
只能由 JPA 实现操作。
请注意,当您在 Reservation
class 级别上声明 @Setter
时也会发生此暴露。
这可以避免从 class 级别删除注释并注释每个字段以公开,但更简单的方法是使用继承。
您可以创建一个基础class,例如:
@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;
}
请注意,字段 id
没有 setter。在 class 上方扩展为:
@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;
}
和构造函数 & setter 如下:
Reservation r1 = new Reservation();
Reservation r2 = new Reservation(room, customer, dateFrom, dateTo);
r1.setRoom(room);
r1.setCustomer(customer);
r1.setDateFrom(dateFrom);
r1.setDateTo(dateTo);
并且没有办法 - 其他 JPA 使用的反射 - 设置字段 id
.
我不知道如何 spring-data-jpa exactly does setting the id
but as there is a keyword JPA and tag jpa 我假设这是 JPA 的事情,并且实际上根本不需要字段 id
的 setter。
Lombok 部分的评论:无法从 @AllArgsConstructor
中排除字段(不使用继承)。对于有限的构造函数,您只能使用 @RequiredArgsConstructor
,但这通常对 JPA 实体没有帮助。
我的解决方案是当 id 由 jpa 自动生成并且您使用 lombok 来避免样板代码时。
@Entity
@Getter
@Setter
@ToString
@RequiredArgsConstructor
@AllArgsConstructor
public class Patient {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long reg;
@NotNull
private String name;
@NotNull
private String gender;
@NotNull
private String specimen;
@NotNull
private String contact;
@NotNull
private String cnic;
@NotNull
private String referred_by;
public Patient(String name, String gender, String specimen, String contact, String cnic, String referred_by) {
this.name = name;
this.gender = gender;
this.specimen = specimen;
this.contact = contact;
this.cnic = cnic;
this.referred_by = referred_by;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
Patient patient = (Patient) o;
return reg != null && Objects.equals(reg, patient.reg);
}
@Override
public int hashCode() {
return getClass().hashCode();
}
}
简单地使用了一个不包括 id 字段的自定义构造函数并且它有效。
使用 spring-boot
和 JPA 我有一个 Entity
我想使用 lombok 来减少样板代码。但是在我的实体中有 id
字段。我应该将它放在带有 @AllArgsConstructor
的构造函数参数中,还是应该将其从参数列表中删除(不知何故,如何?)因为它是使用 @id
和 @GeneratedValue
注释自动生成的?
代码:
@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;
}
在这种情况下 spring-data
使用 setter 来设置值,因此不需要 @AllArgsConstructor
。
对于您在代码中的问题:
@AllArgsConstructor // ? is id in constuctor needed?
不,不需要。另外,对于你标题中的问题:
Is using id field in @AllArgsConstructor while using Spring JPA correct?
字段 id
不建议将其暴露给任何构造函数或 setter 除非有充分的理由。字段 id
只能由 JPA 实现操作。
请注意,当您在 Reservation
class 级别上声明 @Setter
时也会发生此暴露。
这可以避免从 class 级别删除注释并注释每个字段以公开,但更简单的方法是使用继承。
您可以创建一个基础class,例如:
@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;
}
请注意,字段 id
没有 setter。在 class 上方扩展为:
@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;
}
和构造函数 & setter 如下:
Reservation r1 = new Reservation();
Reservation r2 = new Reservation(room, customer, dateFrom, dateTo);
r1.setRoom(room);
r1.setCustomer(customer);
r1.setDateFrom(dateFrom);
r1.setDateTo(dateTo);
并且没有办法 - 其他 JPA 使用的反射 - 设置字段 id
.
我不知道如何 spring-data-jpa exactly does setting the id
but as there is a keyword JPA and tag jpa 我假设这是 JPA 的事情,并且实际上根本不需要字段 id
的 setter。
Lombok 部分的评论:无法从 @AllArgsConstructor
中排除字段(不使用继承)。对于有限的构造函数,您只能使用 @RequiredArgsConstructor
,但这通常对 JPA 实体没有帮助。
我的解决方案是当 id 由 jpa 自动生成并且您使用 lombok 来避免样板代码时。
@Entity
@Getter
@Setter
@ToString
@RequiredArgsConstructor
@AllArgsConstructor
public class Patient {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long reg;
@NotNull
private String name;
@NotNull
private String gender;
@NotNull
private String specimen;
@NotNull
private String contact;
@NotNull
private String cnic;
@NotNull
private String referred_by;
public Patient(String name, String gender, String specimen, String contact, String cnic, String referred_by) {
this.name = name;
this.gender = gender;
this.specimen = specimen;
this.contact = contact;
this.cnic = cnic;
this.referred_by = referred_by;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
Patient patient = (Patient) o;
return reg != null && Objects.equals(reg, patient.reg);
}
@Override
public int hashCode() {
return getClass().hashCode();
}
}
简单地使用了一个不包括 id 字段的自定义构造函数并且它有效。