繁体   English   中英

在使用 Spring JPA 时在 @AllArgsConstructor 中使用 id 字段是否正确?

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

使用spring-boot和 JPA 我有一个Entity ,我想使用 lombok 来减少样板代码。 但是在我的实体中有id字段。 我应该把它放在带有@AllArgsConstructor的构造函数 arguments 中,还是应该将它从参数列表中删除(不知何故,如何?),因为它是使用@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;    
}

对于您在代码中的问题:

@AllArgsConstructor // ? 需要构造函数中的 id 吗?

不,不需要。 此外,对于您在标题中的问题:

使用 Spring JPA 时在@AllArgsConstructor 中使用 id 字段是否正确?

除非有很好的理由,否则不建议将字段id暴露给任何构造函数或 setter。 字段id应仅由 JPA 实现操作。

请注意,当您在Reservation类级别声明@Setter时,也会发生此公开。

这可以避免从类级别删除注释并注释每个字段以公开但更简单的方法是使用继承。

您可以创建一个基类,如:

@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设置器。 扩展上面的类,如:

@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;    
}

构造函数和设置器将如下所示:

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

我不知道究竟是如何设置id但由于有一个关键字 JPA 和标签我认为这是一个 JPA 东西,实际上根本不需要字段id设置器。

在这种情况下, spring-data使用 setter 来设置值,因此@AllArgsConstructor

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 字段的自定义构造函数即可。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM