Hibernate映射多对一关系
背景
一个项目item,对应多个Bid。
简单单向版
Hibernate
Bid 到 item之间简单关联,先不考虑其他情况。
Hibernate 之间的映射如下:
<class name="Bid" table="BID">
...
<many-to-one
name="item"
column="ITEM_ID"
class="Item"
not-null="true"/>
</class>
此处为单向表,BID表中item_id为ITEM表主键的一个外键。其中not null则指定bid必须关联一个item。
JPA
public class Bid{
…
@ManyToOne(targetEntity = auction.model.Item.class)
@JoinColumn(name=”ITEM_ID”,nullable=false)
private Item item;
…
}
targetEntity一般而言是可选的,,对于字段而言是隐式的,在复杂的领域模型很有用。JoinColumn也可选,默认外键名称为item加id,用下划线相连,另外,外键为not null,就需要使用nullable=false。
双向关联
Hibernate
增加ITEM到BID的一对多的关联。
ITEM不仅需要添加BID之间的关联,还需要添加相应BID的脚手架代码如下:
public class Item{
...
private set bids = new HashSet();
public void setBids(set bids){
this.bids = bids;
}
public set getBids(){
return bids;
}
//脚手架代码在Entity中
public void addBid(Bid bid){
bid.setItem(this);//实现相互托管关联
bids.add(bid);
}
...
}
一对多的基本映射:
<class name="item" table="ITEM">
...
<set name=bids>
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
</class>
从上述可看出,用one-to-many映射了集合的内容,且该值类型包含了对示例的引用。可以看出,到集合的引用set不需要table属性。其中key映射的是Bid表的外键列,即已经在关系的另一侧映射的同一个列。
现在出现一个问题,此时的关联实际上还是属于两个单向关联。由于之前的单项关联指定了not null =true,这里映射到同一个外键不需要重复指定。此时需要指定两个关联由哪一方进行控制,inverse属性告诉hibernate,集合是many-to-one关联在另一侧的一个镜像:
<class name="item" table="ITEM">
...
<set name=bids inverse=true>
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
</class>
说明:
由inverse控制被控制方,此处只有bid.setItem()时,才能达到自己想要的。
需要转换反向端时,many-to-one没有inverse属性,但是可以用update=false、insert=false有效忽略任何update、insert语句。
JPA
用jpa注解这个反向集合
public class Item{
...
@oneToMany(mappedBy = "item")
private Set(Bid) bids = new HashSet<Bid>();
...
}
OneToOne,OneToMany,ManyToMany上才有mappedBy,定义在被拥有一方,指向拥有方,拥有方能够自动维护被拥有方的关系。
mappedBy跟joinColumn/JoinTable总是处于互斥的一方。
级联删除
级联是有方向性的,定义在关联对象的被关联字段上面,同inverse。
Hibernate
<set name="bids" inverse="true" cascade="save-update,delete">
...
JPA
public class Item {
@OneToMany(cascade={
CasecadeType.PERSIST,
CasecadeType.MERGE,
CasecadeType.REMOVE},
mappedBy = "item")
private Set(Bid) bids = new HashSet<Bid>();
}
孤儿删除
只有在一对多的环境下才有孤儿删除。
在一对多的关系中,可以将一的一方认为是父方.将多的一方认为是子方.孤儿删除:在解除了父子关 系的时候.将子方记录就直接删除。
在XML中开启
<set name="bids" inverse="true" casecade="save-update,delete,delete-orphan">
...
Hibernate扩展使用
public class Item{
@OneToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE,Cascade.Type.REMOVE},mappedBy = "item")
@org.hibernate.annotations.Cascade(value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
private Set<Bid> bids = new HashSet<Bid>();
}