有什么区别:
@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;
...
}
注释@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;
}
@JoinColumn可以在关系的双方使用。问题是关于在@OneToMany端使用@JoinColumn(罕见情况)。这里的重点是物理信息复制(列名)以及未优化的SQL查询,这将产生一些额外的UPDATE语句。
根据文件:
由于在JPA规范中,多对一(几乎)总是双向关系的所有者方,所以一对多关联由@OneToMany(mappedBy=…)
@Entity
public class Troop {
@OneToMany(mappedBy="troop")
public Set<Soldier> getSoldiers() {
...
}
@Entity
public class Soldier {
@ManyToOne
@JoinColumn(name="troop_fk")
public Troop getTroop() {
...
}
部队通过部队属性与士兵产生双向多的关系。您不必(一定不)在mappedBy端中定义任何物理映射。
要将一个双向的1映射到多,将一对多的端映射为所属端,您必须删除mappedBy元素,并将多对一的@JoinColumn设置为可插入的,并将可更新的设置为false。此解决方案未经过优化,将产生一些额外的UPDATE语句。
@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() {
...
}
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;
}
}
@Entity
public class Company {
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "company_id_ref", referencedColumnName = "company_id")
private List<Branch> branches;
...
}
这将给出下面的Hibernate日志
Hibernate: select nextval ('hibernate_sequence')
Hibernate: select nextval ('hibernate_sequence')
Hibernate: insert into company (name, company_id) values (?, ?)
Hibernate: insert into branch (company_id_ref, name, id) values (?, ?, ?)
Hibernate: update branch set company_id_ref=? where id=?
And
@Entity
public class Company {
@OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY,
mappedBy = "company")
private List<Branch> branches;
...
}
这将给出下面的Hibernate日志
Hibernate: select nextval ('hibernate_sequence')
Hibernate: select nextval ('hibernate_sequence')
Hibernate: insert into company (name, company_id) values (?, ?)
Hibernate: insert into branch (company_id_ref, name, id) values (?, ?, ?)
我们可以清楚地看到@joinColumn将导致额外的更新查询。
所以你不需要显式地将父实体设置为子实体,
这是我们在使用mappedBy时要做的
拯救有父母陪伴的孩子