有什么区别:

@Entity
public class Company {

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

and

@Entity
public class Company {

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

当前回答

JPA是一个分层的API,不同的级别有自己的注释。最高级别是(1)实体级别,它描述持久类,然后是(2)关系数据库级别,它假设实体映射到关系数据库,以及(3)java模型。

一级注释:@Entity, @Id, @OneToOne, @OneToMany, @ManyToOne, @ManyToMany。 仅使用这些高级注释就可以在应用程序中引入持久性。但是您必须根据JPA所做的假设来创建数据库。这些注释指定了实体/关系模型。

二级注释:@Table, @Column, @JoinColumn,… 如果您对JPA的默认值不满意,或者需要映射到现有数据库,则影响从实体/属性到关系数据库表/列的映射。这些注释可以被看作是实现注释,它们指定了映射应该如何完成。

在我看来,最好是尽可能多地使用高级注释,然后根据需要引入低级注释。

要回答这些问题:@OneToMany/mappedBy是最好的,因为它只使用来自实体域的注释。@oneToMany/@JoinColumn也很好,但它使用了一个实现注释,这并不是严格必要的。

其他回答

让我简单说一下。 不管映射如何,您都可以在任意一侧使用@JoinColumn。

我们把它分成三种情况。 1)分公司到公司的单向映射。 2)公司到分公司的双向映射。 3)从公司到分公司只能单向映射。

因此任何用例都可以归入这三类。让我来解释一下如何使用@JoinColumn和mappedBy。 1)分公司到公司的单向映射。 在Branch表中使用JoinColumn。 2)公司到分公司的双向映射。 使用mappedBy在公司表描述@Mykhaylo Adamovych的回答。 3)公司到分公司的单向映射。 在Company表中使用@JoinColumn即可。

@Entity
public class Company {

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

这就是说,在基于外键“courseId”映射在分支表中,得到我所有分支的列表。注意:在这种情况下你不能从分支获取公司,从公司到分支只存在单向映射。

我不同意Óscar López这里接受的答案。这个答案是不准确的!

它不是@JoinColumn,这表明该实体是关系的所有者。取而代之的是@ManyToOne注释(在他的例子中)。

关系注释如@ManyToOne, @OneToMany和@ManyToMany告诉JPA/Hibernate创建映射。默认情况下,这是通过一个单独的连接表来完成的。

@JoinColumn

@JoinColumn的目的是创建一个连接列(如果有的话) 不存在。如果是,则可以使用此注释 命名连接列。

的MappedBy

MappedBy参数的目的是指示JPA: Do NOT 创建另一个连接表,因为已经映射了关系 通过这种关系的相反实体。

请记住:MappedBy是关系注释的一个属性,其目的是生成一种机制来关联两个实体,默认情况下,它们通过创建一个连接表来实现。MappedBy在一个方向上停止这个过程。

The entity not using MappedBy is said to be the owner of the relationship because the mechanics of the mapping are dictated within its class through the use of one of the three mapping annotations against the foreign key field. This not only specifies the nature of the mapping but also instructs the creation of a join table. Furthermore, the option to suppress the join table also exists by applying @JoinColumn annotation over the foreign key which keeps it inside the table of the owner entity instead.

总的来说:@JoinColumn要么创建一个新的连接列,要么重命名一个现有的连接列;而MappedBy参数与其他(子)类的关系注释协同工作,以便通过连接表或在所有者实体的关联表中创建外键列来创建映射。

为了说明MapppedBy是如何工作的,考虑下面的代码。如果MappedBy参数被删除,那么Hibernate实际上会创建两个连接表!为什么?因为在多对多关系中存在对称性,Hibernate没有理由选择一个方向而不是另一个方向。

因此,我们使用MappedBy告诉Hibernate,我们已经选择了另一个实体来指示两个实体之间关系的映射。

@Entity
public class Driver {
    @ManyToMany(mappedBy = "drivers")
    private List<Cars> cars;
}

@Entity
public class Cars {
    @ManyToMany
    private List<Drivers> drivers;
}

在owner类中添加@JoinColumn(name = "driverID")(见下文),将防止创建连接表,相反,在Cars表中创建一个driverID外键列来构建映射:

@Entity
public class Driver {
    @ManyToMany(mappedBy = "drivers")
    private List<Cars> cars;
}

@Entity
public class Cars {
    @ManyToMany
    @JoinColumn(name = "driverID")
    private List<Drivers> drivers;
}

mappedBy注释理想情况下应该总是在双向关系的父端(Company类)中使用,在这种情况下,它应该在Company类中指向子类(分支类)的成员变量' Company '

注释@JoinColumn用于指定加入实体关联的映射列,这个注释可以在任何类(父类或子类)中使用,但理想情况下,它应该只用于一方(无论是在父类或在子类中,而不是在两者中)在这种情况下,我在双向关系的子方面(分支类)中使用它,指示分支类中的外键。

下面是工作示例:

母公司,公司

@Entity
public class Company {


    private int companyId;
    private String companyName;
    private List<Branch> branches;

    @Id
    @GeneratedValue
    @Column(name="COMPANY_ID")
    public int getCompanyId() {
        return companyId;
    }

    public void setCompanyId(int companyId) {
        this.companyId = companyId;
    }

    @Column(name="COMPANY_NAME")
    public String getCompanyName() {
        return companyName;
    }

    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }

    @OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL,mappedBy="company")
    public List<Branch> getBranches() {
        return branches;
    }

    public void setBranches(List<Branch> branches) {
        this.branches = branches;
    }


}

子类,分支

@Entity
public class Branch {

    private int branchId;
    private String branchName;
    private Company company;

    @Id
    @GeneratedValue
    @Column(name="BRANCH_ID")
    public int getBranchId() {
        return branchId;
    }

    public void setBranchId(int branchId) {
        this.branchId = branchId;
    }

    @Column(name="BRANCH_NAME")
    public String getBranchName() {
        return branchName;
    }

    public void setBranchName(String branchName) {
        this.branchName = branchName;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="COMPANY_ID")
    public Company getCompany() {
        return company;
    }

    public void setCompany(Company company) {
        this.company = company;
    }


}

注释@JoinColumn表示该实体是关系的所有者(也就是说:对应的表有一个指向引用表的外键的列),而属性mappedBy表示这一侧的实体是关系的逆,所有者位于“另一个”实体中。这也意味着您可以从用“mappedBy”注释的类中访问另一个表(完全双向关系)。

特别是,对于问题中的代码,正确的注释应该是这样的:

@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;
}

JPA是一个分层的API,不同的级别有自己的注释。最高级别是(1)实体级别,它描述持久类,然后是(2)关系数据库级别,它假设实体映射到关系数据库,以及(3)java模型。

一级注释:@Entity, @Id, @OneToOne, @OneToMany, @ManyToOne, @ManyToMany。 仅使用这些高级注释就可以在应用程序中引入持久性。但是您必须根据JPA所做的假设来创建数据库。这些注释指定了实体/关系模型。

二级注释:@Table, @Column, @JoinColumn,… 如果您对JPA的默认值不满意,或者需要映射到现有数据库,则影响从实体/属性到关系数据库表/列的映射。这些注释可以被看作是实现注释,它们指定了映射应该如何完成。

在我看来,最好是尽可能多地使用高级注释,然后根据需要引入低级注释。

要回答这些问题:@OneToMany/mappedBy是最好的,因为它只使用来自实体域的注释。@oneToMany/@JoinColumn也很好,但它使用了一个实现注释,这并不是严格必要的。