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.accident
和Accident.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 & @OneToOne 关联到不可为空的实体
码农小汪-Hibernate学习8-hibernate关联关系注解表示@OneToMany mappedBy @ManyToMany @JoinTable