单向多对多关系映射
多对多其实是个很复杂的关系,hibernate在进行处理的时候借助中间表或者中间类。中间表是在映射文件的关联标签(比如集合标签<set>)中由table属性指定的由hibernate自动生成的表,它只有两个字段,分别由<key>和<many-to-many>标签的table属性指定,作为外键分别用来指向关联双方表的主键。中间类就是把我们的中间表抽象生成一个实体类,在映射的时候分别和两个关联类构成一对多的关系,即演变成两个一对多来处理。
以下用中间表的例子来说明单向多对多关系映射:运动员(player)与角色(role)就是典型的多对多关系。
首先创建player,role类分别对应的表格:sxt_hibernate_player,sxt_hibernate_role,和中间表sxt_hibernate_player_role(在MySQL环境中)代码如下:
create table sxt_hibernate_player(
id int(11) not null auto_increatement,
name varchar(16),
primary key(id)
)ENGINE=InnoDB DEFAULT CHARSET=gbk;
create table sxt_hibernate_role(
id int(11) not null auto_increatement,
name varchar(16),
primary key(id)
)ENGINE=InnoDB DEFAULT CHARSET=gbk;
create table sxt_hibernate_player_role(
player_id int(11),
role_id int(11)
)ENGINE=InnoDB DEFAULT CHARSET=gbk;
Player实体类:
public class Player {
private Integer id;
private String name;
private Set<Role> roles;
//...省去一系列的setter.getter方法
@Override
public String toString() {
return "Player:" + name;
}
}
Role实体类:
public class Role {
private Integer id;
private String name;
//...省去一系列的setter.getter方法
@Override
public String toString() {
return "Role:" + name;
}
}
映射文件:
Role.hbm.xml
<class name="com.sxt.hibernate.many2many.entity.Role" table="sxt_hibernate_role">
<id name="id" length="4">
<generator length="10"></property>
</class>
Player.hbm.xml
<class name="com.sxt.hibernate.many2many.entity.Player" table="sxt_hibernate_player">
<id name="id" length="4">
<generator length="10"></property>
<!--table="sxt_hibernate_user_role"含义,用来指定中间表 -->
<set name="roles" table="sxt_hibernate_player_role" cascade="save-update">
<!--<key column="user_id">含义,指定中间表中用来指向本表的外键 -->
<key column="player_id"></key>
<!-- column含义,用来指定中间表中用来指向另一端表的外键 -->
<many-to-many column="role_id"></many-to-many>
</set>
</class>
测试类Test:
public class Test{
public static void main(String[] args) {
Session session = HibernateUtils.getSession();
Transaction t = session.beginTransaction();
try {
/**
* 测试插入数据
*/
Role role1=new Role();
role1.setName("后卫");
Role role2=new Role();
role2.setName("前锋");
Role role3=new Role();
role3.setName("中锋");
Player player1=new Player();
player1.setName("姚明");
Set<Role> roles1=new HashSet<Role>();
roles1.add(role3);
player1.setRoles(roles1);
Player player2=new Player();
player2.setName("詹姆斯");
Set<Role> roles2=new HashSet<Role>();
roles2.add(role1);
roles2.add(role2);
roles2.add(role3);
player2.setRoles(roles2);
//能正确保存.每保存player后,都要级联保存它的role,并且级联插入中间表记录.
session.save(player1);
session.save(player2);*/
/**
* 测试加载数据
*/
Player player=(Player)session.load(Player.class, 1);
System.out.println(player);
for(Iterator<Role> iterator=player.getRoles().iterator();iterator.hasNext();){
System.out.println(iterator.next());
}
t.commit();
} catch (HibernateException e) {
e.printStackTrace();
t.rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
}