首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JPA JoinColumn vs mappedBy

JPA JoinColumn vs mappedBy
EN

Stack Overflow用户
提问于 2012-08-14 00:17:29
回答 8查看 539.6K关注 0票数 572

它们之间的区别是什么:

代码语言:javascript
复制
@Entity
public class Company {

    @OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY)
    @JoinColumn(name = "companyIdRef", referencedColumnName = "companyId")
    private List<Branch> branches;
    ...
}

代码语言:javascript
复制
@Entity
public class Company {

    @OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY, 
    mappedBy = "companyIdRef")
    private List<Branch> branches;
    ...
}
EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2012-08-14 01:10:56

@JoinColumn 可以在关系的两端使用。问题是关于在@OneToMany端使用@JoinColumn (罕见的情况)。这里的重点是物理信息重复(列名)以及未优化的SQL查询,这将产生一些额外的UPDATE语句。

根据documentation的说法

由于many to one是(几乎)在JPA规范中总是双向关系的所有者端,所以一对多关联由@OneToMany(mappedBy=...)注释

代码语言:javascript
复制
@Entity
public class Troop {
    @OneToMany(mappedBy="troop")
    public Set<Soldier> getSoldiers() {
    ...
}

@Entity
public class Soldier {
    @ManyToOne
    @JoinColumn(name="troop_fk")
    public Troop getTroop() {
    ...
} 

通过部队属性,TroopSoldier具有双向的一对多关系。您不必(一定不能)在mappedBy端定义任何物理映射。

要映射一个双向的一对多,将一对多作为拥有方的,您必须删除mappedBy元素,并将多对一@JoinColumn设置为insertable,将updatable设置为false。此解决方案未经过优化,并将生成一些额外的UPDATE语句。

代码语言:javascript
复制
@Entity
public class Troop {
    @OneToMany
    @JoinColumn(name="troop_fk") //we need to duplicate the physical information
    public Set<Soldier> getSoldiers() {
    ...
}

@Entity
public class Soldier {
    @ManyToOne
    @JoinColumn(name="troop_fk", insertable=false, updatable=false)
    public Troop getTroop() {
    ...
}
票数 243
EN

Stack Overflow用户

发布于 2012-08-14 00:20:09

注释@JoinColumn表明此实体是关系的所有者(即:对应的表有一个列,该列具有指向被引用表的外键),而属性mappedBy表明这一端的实体是关系的反面,并且所有者驻留在"other“实体中。这也意味着您可以从使用"mappedBy“(全双向关系)注释的类中访问另一个表。

特别是,对于问题中的代码,正确的注释将如下所示:

代码语言:javascript
复制
@Entity
public class Company {
    @OneToMany(mappedBy = "company",
               orphanRemoval = true,
               fetch = FetchType.LAZY,
               cascade = CascadeType.ALL)
    private List<Branch> branches;
}

@Entity
public class Branch {
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "companyId")
    private Company company;
}
票数 594
EN

Stack Overflow用户

发布于 2018-06-27 13:55:04

单向一对多关联

如果将@OneToMany注释与@JoinColumn一起使用,则会有一个单向关联,如下图中父Post实体和子PostComment之间的关联:

当使用单向一对多关联时,只有父端映射该关联。

在此示例中,仅Post实体将定义到子PostComment实体的@OneToMany关联:

代码语言:javascript
复制
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "post_id")
private List<PostComment> comments = new ArrayList<>();

双向一对多关联

如果使用具有mappedBy属性集的@OneToMany,则具有双向关联。在我们的示例中,两个Post实体都有一个PostComment子实体的集合,而子PostComment实体又有一个对父Post实体的引用,如下图所示:

PostComment实体中,post实体属性的映射方式如下:

代码语言:javascript
复制
@ManyToOne(fetch = FetchType.LAZY)
private Post post;

我们将fetch属性显式设置为FetchType.LAZY的原因是,默认情况下,所有@ManyToOne@OneToOne关联都会被急切地获取,这可能会导致N+1查询问题。

Post实体中,comments关联映射如下:

代码语言:javascript
复制
@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL,
    orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();

@OneToMany注释的mappedBy属性引用了子PostComment实体中的post属性,通过这种方式,Hibernate知道双向关联是由@ManyToOne端控制的,后者负责管理此表关系所基于的外键列值。

对于双向关联,您还需要有两个实用程序方法,如addChildremoveChild

代码语言:javascript
复制
public void addComment(PostComment comment) {
    comments.add(comment);
    comment.setPost(this);
}

public void removeComment(PostComment comment) {
    comments.remove(comment);
    comment.setPost(null);
}

这两种方法确保双向关联的两端是同步的。如果不同步两端,Hibernate不能保证关联状态更改将传播到数据库。

选择哪一个?

单向@OneToMany关联的性能不是很好,因此您应该避免使用它。

您最好使用效率更高的双向@OneToMany

票数 103
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11938253

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档