我是hibernate的新手,需要使用一对多和多对一的关系。它是我对象中的双向关系,因此我可以从任一方向遍历。 mappedBy
是推荐的方法,但我无法理解。有人可以解释一下:
为了我的例子,这里是带注释的类:
Airline
OWNS很多 AirlineFlights
AirlineFlights
属于 ONE Airline
航空公司:
@Entity
@Table(name="Airline")
public class Airline {
private Integer idAirline;
private String name;
private String code;
private String aliasName;
private Set<AirlineFlight> airlineFlights = new HashSet<AirlineFlight>(0);
public Airline(){}
public Airline(String name, String code, String aliasName, Set<AirlineFlight> flights) {
setName(name);
setCode(code);
setAliasName(aliasName);
setAirlineFlights(flights);
}
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="IDAIRLINE", nullable=false)
public Integer getIdAirline() {
return idAirline;
}
private void setIdAirline(Integer idAirline) {
this.idAirline = idAirline;
}
@Column(name="NAME", nullable=false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = DAOUtil.convertToDBString(name);
}
@Column(name="CODE", nullable=false, length=3)
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = DAOUtil.convertToDBString(code);
}
@Column(name="ALIAS", nullable=true)
public String getAliasName() {
return aliasName;
}
public void setAliasName(String aliasName) {
if(aliasName != null)
this.aliasName = DAOUtil.convertToDBString(aliasName);
}
@OneToMany(fetch=FetchType.LAZY, cascade = {CascadeType.ALL})
@JoinColumn(name="IDAIRLINE")
public Set<AirlineFlight> getAirlineFlights() {
return airlineFlights;
}
public void setAirlineFlights(Set<AirlineFlight> flights) {
this.airlineFlights = flights;
}
}
AirlineFlights:
@Entity
@Table(name="AirlineFlight")
public class AirlineFlight {
private Integer idAirlineFlight;
private Airline airline;
private String flightNumber;
public AirlineFlight(){}
public AirlineFlight(Airline airline, String flightNumber) {
setAirline(airline);
setFlightNumber(flightNumber);
}
@Id
@GeneratedValue(generator="identity")
@GenericGenerator(name="identity", strategy="identity")
@Column(name="IDAIRLINEFLIGHT", nullable=false)
public Integer getIdAirlineFlight() {
return idAirlineFlight;
}
private void setIdAirlineFlight(Integer idAirlineFlight) {
this.idAirlineFlight = idAirlineFlight;
}
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="IDAIRLINE", nullable=false)
public Airline getAirline() {
return airline;
}
public void setAirline(Airline airline) {
this.airline = airline;
}
@Column(name="FLIGHTNUMBER", nullable=false)
public String getFlightNumber() {
return flightNumber;
}
public void setFlightNumber(String flightNumber) {
this.flightNumber = DAOUtil.convertToDBString(flightNumber);
}
}
修改
数据库架构:
AirlineFlights的idAirline为ForeignKey,航空公司没有idAirlineFlights。这使得AirlineFlights成为所有者/识别实体?
理论上,我希望航空公司成为航空公司的所有者。
答案 0 :(得分:259)
MappedBy信号休眠,关系的关键在另一边。
这意味着虽然您将两个表链接在一起,但这些表中只有一个对另一个表有外键约束。 MappedBy允许您仍然从不包含约束的表链接到另一个表。
答案 1 :(得分:134)
通过在两个模型上指定@JoinColumn
,您没有双向关系。你有两个单向关系,并且有一个非常令人困惑的映射。你告诉两个模型他们“拥有”IDAIRLINE专栏。实际上只有其中一个真的应该! “正常”的做法是完全取消@JoinColumn
一侧的@OneToMany
,而是将mappedBy添加到@OneToMany
。
@OneToMany(cascade = CascadeType.ALL, mappedBy="airline")
public Set<AirlineFlight> getAirlineFlights() {
return airlineFlights;
}
告诉Hibernate“在我找到配置的东西上查看名为'airline'的bean属性。”
答案 2 :(得分:16)
mappedby
说明了一切,它告诉hibernate不要映射这个字段。它已经被这个字段映射[name =&#34; field&#34;]
field位于另一个实体(name of the variable in the class not the table in the database)
..
如果你不这样做,hibernate将映射这两个关系,因为它不是 相同的关系
所以我们需要告诉hibernate只在一侧进行映射并在它们之间进行协调。
答案 3 :(得分:15)
在关系数据库系统中,one-to-many
table relationship如下所示:
请注意,该关系基于子表中的外键列(例如post_id
)。
因此,在管理one-to-many
表关系时,只有一个事实来源。
现在,如果您采用的双向实体关系映射到我们之前见过的one-to-many
表关系:
看看上面的图,您会发现有两种方法可以管理这种关系。
在Post
实体中,您拥有comments
集合:
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
并且,在PostComment
中,post
关联被映射如下:
@ManyToOne(
fetch = FetchType.LAZY
)
@JoinColumn(name = "post_id")
private Post post;
因为有两种表示外键列的方法,所以在将关联状态更改转换为其等效的外键列值修改时,必须定义哪个是真相的来源。
mappedBy
属性告诉@ManyToOne
端负责管理外键列,并且该集合仅用于获取子实体并将父实体状态更改级联为子实体(例如,删除父实体也应该删除子实体。
现在,即使您定义了mappedBy
属性,并且子端@ManyToOne
关联管理“外键”列,您仍然需要同步双向关联的两端。
做到这一点的最佳方法是添加以下两个实用程序方法:
public void addComment(PostComment comment) {
comments.add(comment);
comment.setPost(this);
}
public void removeComment(PostComment comment) {
comments.remove(comment);
comment.setPost(null);
}
addComment
和removeComment
方法可确保双方同步。因此,如果我们添加一个子实体,则该子实体需要指向父实体,并且该父实体应在子集合中包含该子实体。
有关同步所有双向实体关联类型的最佳方法的更多详细信息,请查看this article。
答案 4 :(得分:10)
mappedby =&#34;在另一个类中创建的同一类实体的对象“
注意:-Mapped只能在一个类中使用,因为一个表必须包含外键约束。如果映射的可以应用于两侧,那么它从两个表中删除外键而没有外键与b / w两个表没有关系。
注意: - 它可用于以下注释: - 1. @ OneTone 2. @一对多 3. @多对多
注意---它不能用于以下注释: - 1. @多对一
一对一: - 在映射的任何一侧执行,但仅在一侧执行。 它将删除应用它的类的表上的额外外键约束列。
例如。如果我们在员工对象的Employee类中应用映射,那么将删除Employee表中的外键。
答案 5 :(得分:1)
mappedBy 属性表征双向关联,必须在父端设置。换句话说,对于双向@OneToMany 关联,在父端将mappedBy 设置为@OneToMany,并在mappedBy 引用的子端添加@ManyToOne。通过mappedBy,双向@OneToMany 关联表明它反映了@ManyToOne 子端映射。
答案 6 :(得分:0)
您开始使用ManyToOne映射,然后将BiTirectMany映射也用于BiDirectional方式。 然后在OneToMany端(通常是您的父表/类),您必须提到“mappedBy”(映射由子表/类中完成),因此hibernate不会在DB中创建EXTRA映射表(如TableName = parent_child)。