一对多的关系在我们的日常生活中并不少见, 比如说, 一个用户可以有多个手机.
public class User implements java.io.Serializable {
private Set equipments = new HashSet(0);
public Set getEquipments() {
return this.equipments;
}
public void setEquipments(Set equipments) {
this.equipments = equipments;
}
}
public class Equipment implements java.io.Serializable {
private User user;
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
}
上面的两个类中我们可以看到, 一个User有多个equipment, 而每个equipment只能被一个User所拥有.
所以在User.hbm.xml中这样配置
<class name="com.*.cd.pojo.User" table="users" schema="public" dynamic-insert="true" dynamic-update="true"> <id name="userId" type="java.lang.Integer"> <column name="user_id" /> <generator class="sequence"> <param name="sequence">seq_cd_user_id</param> </generator> </id> <set name="equipments" inverse="true" lazy="true" > <key> <column name="user_id" /> </key> <one-to-many class="com.*.cd.pojo.Equipment" /> </set> </class>
我们知道, 在一对多关系中, 多方都有一个附带的属性, 就是一方的主键作为外键. 所以在User.hbm.xml中,的Set里面要有一个<key></key>属性. 作为作为equipment的外键.
inverse . 默认为false. 在这里指定是由谁来维护这个主外键关系的. 在这里inverse="true" 表示该实体是对立面, 不具备维护user_id的权限. 修改此集合不会影响到关联表.
lazy: 加载User的时候是否及时加载equipments. 默认为false. 这里lazy="true" , 加载User的时候并不会立即加载其儿子.
<one-to-many class="com.*.cd.pojo.Equipment" />指定了多方是Equipment.
下面我们来看看多方是怎么配置的.
<class name="....*.Equipment" table="equipments" schema="public" dynamic-insert="true" dynamic-update="true"> <id name="eacId" type="java.lang.Integer"> <column name="eac_id" /> <generator class="foreign" > <param name="property">EACard</param> </generator> </id> <many-to-one name="user" class="....*.User" fetch="select" > <column name="user_id" /> </many-to-one> </class>
在这里简单说明一下. name="....*.Equipment" 是对应的全限类名, table="equipments" 是对应的表名, schema="public" 根据数据库不同而不同.
而dynamic-insert和dynamic-update会根据实际情况生成动态的inser和update语句.
dynamic-insert="true" 的时候,他会将属性不为null的属性拼接成sql语句插入,
dynamic-update="true"的时候,会只更新哪些改变过的字段.
这里, equipment是多方, user是一方, 所以用到<many-to-one>
name="user" 是equipment中的一个属性 , class="...*.User" 会根据User类实例化一个user对象.
fetch="select" 指定了关联对象的加载方式是select . 默认为join.
当fetch = "select"时, 首先会加载此equipment对象, 然后根据此equipment的外键userId加载User对象, 会形成n+1此查询, 而fetch = "join"时, 会根据外键关联一次性加载equipment和User对象.
当lazy="true"时, 就不会加载关联对象.
一对多的关键点.
在一方配置<set></set>属性中用inverse="true"和false来设置自己是否有权限维护主外键关系. 默认是false由自己维护, 当为true时. 将此权限交由多方维护.
set中的<key><column name="user_id" /> </key>指定此主键为对方的外键.
<one-to-many class=".....*.Equipment" /> 说明多方的实例对象由Equipment生成.
在多方的配置就只是一个
<many-to-one name="user" class="User" fetch="select">
<column name="user_id" /><!--外键-->
</many-to-one>
在多对多关系中, 例如角色和用户的关系, 一个用户可以是多个角色, 而每个角色可以指派给多个用户. 在这种情况下我们会将多对多化解为两个一对多处理.