Hibernate @OneToMany 关联尝试设置空 FK 值

Hibernate @OneToMany association tries to set a null FK value

我有以下简单示例。当它运行时,我看到使用自动生成的 ID 生成的 QuoteRequest 对象。接下来,我看到正在生成 Accidents 对象,但是正在插入的 quote_request_id 为空,所以我得到一个错误:

列 'quote_request_id' 不能为空

@Entity
@Table(name = "Quotes")
public class QuoteRequest
{
    public QuoteRequest(){}

    @Id
    @Column(name = "quote_request_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long QuoteRequestId;


    @OneToMany(mappedBy = "quoteRequest", cascade = CascadeType.ALL)
    @OrderColumn(name = "accidents_id")
    private Accidents[] accidents;

    // Getters and setters
}

@Entity
@Table(name = "Accidents")
public class Accidents
{
    public Accidents()
    {
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "accidents_id")
    private long AccidentId;


    @Column(name = "amount", nullable = false)
    private Float amount;

    @ManyToOne(optional = false, cascade = CascadeType.ALL)
    @JoinColumn(name = "quote_request_id", nullable = false)
    private QuoteRequest quoteRequest;

    // Getters and setters
}

为什么不将新生成的 ID 插入事故列?

首先,将 @OneToMany 从使用数组更改为使用 List

@OneToMany(mappedBy = "quoteRequest", cascade = CascadeType.ALL)
@OrderColumn(name = "accidents_id")
private List<Accidents> accidents = new ArrayList()<>;

确保设置关联的两侧:

QuoteRequest quoteRequest = ...
Accidents accidents = ...

quoteRequest.getAccidents().add(accident);
accident.setQuoteRequest(quoteRequest);

When creating Accidents, I don't set the quoteRequest property. Should I be doing anything with that? Do I need to have a bi-directional relationship?

就是这个原因。

首先,"Do I need to have a bi-directional relationship?"。好吧,你是唯一知道的人。但是,您已经拥有双向关系。顺便说一句,Accident 方拥有这种关系。这意味着,对于数据库列 Accident.quote_req_id 依赖于字段 Accident.quoteRequest。由于您尚未填充该字段,Hibernate 假设它为空。因此它正在插入空值。所有预期行为。

总之,要确保QuoteRequest.accidentAccident.quoteRequest一致,例如:

class QuoteRequest {
    private List<Accident> accidents = new ArrayList<>();  // I prefer List or Set

    public void setAccidents(List<Accident> accidents) {
        this.accidents.clear();
        if (accidents != null) {
            // intentionally keeping another list, to be defensive and not
            // affected by subsequent change in the caller's list
            this.accidents = this.accidents.addAll(accidents);
            for (Accident accident:accidents) {
                accident.setQuoteRequest(this);
            }
        }
    }
}

class Accident {
    private QuoteRequest quoteRequest;
    public setQuoteRequest(QuoteRequest quoteRequest) {
        // there will be something more...
        this.quoteRequest = quoteRequest;
    }
}

这只是它的外观的一个非常基本的示例。简而言之,您需要 Accident.quoteRequest 设置适当的值。上面的实现还有很多问题,我会留给你(例如,当你之前设置了 accidents 现在被另一个列表替换)