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

Posted

技术标签:

【中文标题】Hibernate @OneToMany 关联尝试设置空 FK 值【英文标题】:Hibernate @OneToMany association tries to set a null FK value 【发布时间】:2015-06-03 05:37:31 【问题描述】:

我有以下简单的例子。当它运行时,我看到正在使用自动生成的 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 插入到事故列中?

【问题讨论】:

看起来很奇怪。根据您的配置,当Accidents 被插入时,它应该有quote_request_id 一起插入。我可以知道您使用的是哪个版本的 Hibernate 吗?而且,更重要的是:对于您创建的Accidents 对象,您实际上是否正确设置了它的quoteRequest? (我希望你只在QuoteRequest 一侧设置accidents,但在Accidents 一侧忘记quoteRequest,因为后者是拥有关系的一侧)。一个 OT 问题:您应该将其命名为 Accident 而不是 Accidents,因为它仅代表一次事故 我正在使用 Hibernate 4.3.9.Final 我没有明确地在 Accidents 上分配 quoteRequest。我正在创建事故,将它们添加到 QuoteRequest。创建事故时,我没有设置 quoteRequest 属性。我应该对此做些什么吗?我需要建立双向关系吗?很好的命名。我没有想出它,但我现在坚持它:) 那就是问题所在。会给你答案 好的,很好。另一个注意事项,我从 JSON 对象序列化它。所以我的 QuoteRequest 和 Accidents 是从 JSON 数据自动填充的 mappedBy = "quoteRequest" 表示它是双向关系,并且 Accidents 拥有该关系 【参考方案1】:

首先,将 @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);

【讨论】:

【参考方案2】:

创建事故时,我没有设置 quoteRequest 属性。我应该对此做些什么吗?我需要建立双向关系吗?

这就是原因。

首先,“我需要建立双向关系吗?”。好吧,你是唯一能说出来的人。但是,您已经建立了双向关系。顺便说一句,Accident 方拥有该关系。这意味着,对于 DB 列 Accident.quote_req_id 依赖于字段 Accident.quoteRequest。由于您尚未填充该字段,Hibernate 假设该字段为空。因此它正在插入null。所有预期的行为。

简而言之,你应该确保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 现在被另一个列表替换时)

【讨论】:

以上是关于Hibernate @OneToMany 关联尝试设置空 FK 值的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate OneToMany 关联在主要以外

Hibernate @OneToMany & @OneToOne 关联到不可为空的实体

码农小汪-Hibernate学习8-hibernate关联关系注解表示@OneToMany mappedBy @ManyToMany @JoinTable

Hibernate - OneToMany - 多列

休眠 OneToMany 和 ManyToOne?

java - 如何在Java Spring中从Hibernate双向OneToMany ManyToOne中检索数据