浅析Spring Data JPA的owning side及foreign key的关系-下
2.1 OneToMany mapping的owning side
对于OneToMany mapping的owning side确认,基本和OneToOne一致,唯一不同的是unidirectional OneToMany mapping,具体情况我们可以到源码中确认。
2.1.1 Bidrection OneToMany的owning side

在OneToMany的关系中,通常我们会将foreign key建在Many的一方,即owning side为Many的一方。
从上图中的描述也可以看出,在bidirectional OneToMany关联关系中,mappedBy标识出Customer为non-owning side,因此Order class为OneToMany关联关系的owning side。
2.1.2 Unidirection OneToMany的owning side

可能让大家困惑的应该是unidirectional OneToMany关联关系,为何foreign key建在Many的一方,但作为non-owning side的Customer class中没有mappedBy标识,而且还引用(使用)了@JoinColumn注解呢?
首先我们来解释一下为什么unidirectional OneToMany中没有mappedBy标识。
1 | // from @OneToMany source code |
从源码解释中,可以看出mappedBy标识不需要在unidiretional OneToMany中显式使用。
接下来我们将解释为什么unidirectional OneToMany会在non-owning side的entity中引用@JoinColumn注解。
2.1.3 浅析@JoinColumn中的source entity和target entity
我们可以看一下@JoinColumn的源码解释

可以看到红色圈的部分,意味着如果是unidirectional OneToMany,那么foreign key应该在target entity中。
此处source entity和target entity又如何区分呢?
我们可以看到@JoinColumn源码解释中的第一段话:
If the join is for a OneToOne or ManyToOne mapping using a foreign key mapping strategy, the foreign key column is in the table of the source entity or embeddable.
这段话表明OneToOne和ManyToOne mapping中,foreign key会在source entity中,然后我们可以观察之前bidirectional OneToMany mapping的代码:
1 | // In Customer class: |
可以看出foreign key存在于Order entity中,即Order entity为@JoinColumn的source entity。
那么也就意味着在ManyToOne mapping中引用(使用) @JoinColumn的entity为source entity(例子中的Order class),而被@JoinColumn注解的Entity为target entity (例子中的Customer class)。
回到我们分析的unidirectional OneToMany的代码例子:
1 | // Example 3: Unidirectional One-to-Many association using a foreign key mapping |
1 | // from @JoinColumn source code |
根据上述分析,对于unidirectional OneToMany,Customer class为non-owning side,foreign key存在于Order class 中。
那么Customer class为unidirectional OneToMany情况下@JoinColumn的source entity。
Order class为unidirectional OneToMany情况下@JoinColumn的target entity。
所以我们需要将@JoinColumn加在getOrders()方法上。
到此解释了unidirectional OneToMany中@JoinColumn如此设定的原因。
3. 总结
以上我们分析了OneToOne和OneToMany的owning side设定策略,对于ManyToMany,基本与前面分析的两种mapping一致。
在分析owning side的过程中,会发现源码中有些解释是较为模糊的,比如source entity, taraget entity。这个时候就需要我们动手写一些demo代码去验证,毕竟“实践是检验真理的唯一标准”。