映射实体关联关系
映射一对一关联
有两种方法,一种按照外键映射,一种按照主键映射。
1.按照外键映射
一个类中有两个一对一关联。
class A{
id;
name;
B home;
B company;
}
class B{
string address;
string street;A a;
}
A表
id
name
home_id//指向B表中的id,外键
company_id//指向B表中的id,外键
B表
address
street
id
A映射文件:
<many-to-one
name="home"
class="B"
column="home_id"
/>
<many-to-one
name="company"
class="B"
column="company_id"
unique="true"//保证唯一
cascsde="all"
/>
B映射文件:
<one-to-one //只能使用一次,所以要映射两次的话,把B定义为抽象类,用两个类继承,让后再每个类中用one-to-one
name="a"
class="A"
property-ref="home"
/>
2.按照主键映射
只有一个一对一关联。
class A{
id;name
B b;
}
class B{
id
address;A a
}
A表
id
name
//这两个表共享主键,id是一样的
B表
id//作为主键的同时,作为外键参照A表
address
A映射文件:
<one-to-one name="b"
class="B"
cascade="true"
/>
B映射文件:
<id>
<generator class="foreign">//OID要用foreign策略
<param name="property">a</param>
</generator>
</id>
<one-to-one name="a"
class="A"
constrained="true"//表示主键id同时作为外键参照A表
/>
映射单向多对多关联
class A{//这两个类是多对多关系
id
name;Set BS = new HashSet();
}
class B{
id
address
}
要建立一个中间表
A表
id
name
B表
id
address
A_B表
A_id//A_id和B_id作为联合主键,A_id作为A表的外键,B_id作为B表的外键
B_id
A映射文件:
<set
name="BS"
table="A_B"
cascade="save-update"
lazy="true"
>
<key column="A_id">
<many-to-many column="B_id" class="B"/>
</set>
也可以用list:
<list
name="BS"
table="A_B"
cascade="save-update"
lazy="true"
>
<key column="A_id"><list-index column="索引字段">
<many-to-many column="B_id" class="B"/>
</list>
映射双向多对多关联关系
双向多对多必须把一端的inverse为true。inverse为true一段可以使用<set>,<bag>。inverse为false的一端,可以使用<set>,<list>,<map>,<idbag>。
1.关联两端使用
class A{
id
name
set BS
}
class B{
id
adress
set AS
}//表和单向多对多一样
A映射文件:
<set
name="BS"
table="A_B"
cascade="save-update"
lazy="true"
>
<key column="A_id">
<many-to-many column="B_id" class="B"/>
</set>
B映射文件
<set
name="AS"
table="A_B"
inverse="true"
cascade="save-update"
lazy="true"
>
<key column="B_id">
<many-to-many column="A_id" class="A"/>
</set>
2.inverse为true的一端使用bag
为什么Inverse为true的那端不能使用list,map之类的呢:因为这些元素有排序。
如果两个类都是list集合,而没有inverse的那端可以更新索引,有inverse的那端不能同步更新索引,所以如果索引变化了就不会同步更新,就出问题。
如果在inverse那端勒种定义的是list,那么就是用bag元素,<bag>和<idbag>的区别是:都允许放重复对象,都不支持索引位置排序,<idbag>要求连接表中一定要有代理主键,<bag>没有这个要求,<bag>一般用于一对多或多对多的inverse端。
<bag
name="AS"
table="A_B"
cascade="save-update"
lazy="true"
>
<key column="B_id">
<many-to-many column="A_id" class="A"/>
</bag>
3.使用组件类集合
两个多对多的类可以使用一个组件类型的类,来实现多对多,而不是用主键当外键关联两个类的表。
calss A{
id
name
set ab//A_B类型
}
class B{
id
adress
Set ba//A_B类型
}
class A_B{//使用组件关联两个多对多的类
A a
B b
name
}
A表
id
name
B表
id
address
A_B表//表中所有字段作为联合主键
A_id//外键
B_id//外键
name
A映射文件:
<set
name="ab"
table="A_B"
cascade=""
lazy=""
>
<key column="A_id">
<composite-element class="A_B">
<parent name="a">
<many-to-one name="b" class="B" column='B_id">
<property>
</composite>
</set>
B的映射文件:
<set
name="ba"
table="A_B"
cascade=""
lazy="" inverse="true"
>
<key column="B_id">
<composite-element class="A_B">
<parent name="b">
<many-to-one name="a" class="A" column='A_id">
<property>
</composite>
</set>
4.把多对多关联分解为两个一对多关联
在组件类型中添加OID,可以打一个多对多拆成两个一对多。
A映射文件:
<set
name="ab"
cascade=""
lazy="" inverse="true"//一对多,一这边最好要加inverse="true"
>
<key column="A_id">
<one-to-many class="A_B">
</set>
B映射文件:
<set
name="ba"
cascade=""
lazy="" inverse="true"//一对多,一这边最好要加inverse="true"
>
<key column="B_id">
<one-to-many class="A_B">
</set>
因为A_B现在有OID了,所以有映射文件:
<class name="" table>
<id>
<property>
<many-to-one name="a" column="A_id" class="A"/>
<many-to-one name="b" column="B_id" class="B"/>
</class>
还没有评论,来说两句吧...