这个星期在看《Hibernate开发指南》,边看边动手做了小例子,先记录下来。
Hibernate的关联关系映射主要有三种:
一对一关联
一对多关联
多对多关联
一、使用*.hbm.xml配置文件做简单示例
一对一关联包括两种形式:主键关联、唯一外键关联
主键关联:两张关联表通过主键形成一对一的映射关系。Hibernate中通过one-to-one节点对一对一关系进行定义。
示例:一个用户User属于一个组Group
User实体类:
Group实体类:
User.hbm.xml
Group.hbm.xml
测试方法:
唯一外键关联:通过增加外键字段实现,这种方式是多对一关系的一个特例。
User类没有变化,Group类中去掉user字段:
User.hbm.xml
Group.hbm.xml
测试方法:
注意:hibernate.cfg.xml的映射文件中不能存在同名文件,即使路径不一样。
二、使用JPA实现*.hbm.xml相同的功能
首先,使用JPA需要更改HibernateSessionFactory中Configuration的实现:private static Configuration configuration = new
AnnotationConfiguration(); 或者在自定义Configuration cfg=new AnnotationConfiguration().configure();
其次,去掉hibernate.cfg.xml中<mapping resource="com/petrochina/onetoone/User.hbm.xml" />部分对映射文件的配置,改为<mapping class="com.petrochina.jpa.User" />
1、一对一
一对一关系有三种情况
示例:用户User、组Group
(1)关联的实体都共享同样的主键
1)一对一双向关联
执行插入测试方法:
Hibernate生成的sql语句如下:
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into t_user (name, id) values (?, ?)
Hibernate: insert into t_group (name, id) values (?, ?)
查询表里的数据
SQL> select * from t_user;
ID NAME
--------------------------------------------------------------------------------
276 csdner
SQL> select * from t_group;
ID NAME
--------------------------------------------------------------------------------
276 developer
可见,User和Group有相同的ID。
执行查询测试方法:
Hibernate生成的sql语句如下:
select user0_.id as id2_2_,
user0_.name as name2_2_,
group1_.id as id3_0_,
group1_.name as name3_0_,
user2_.id as id2_1_,
user2_.name as name2_1_
from t_user user0_
left outer join t_group group1_
on user0_.id = group1_.id
left outer join t_user user2_
on group1_.id = user2_.id
where user0_.id = ?
csdner
developer
可见User和Group通过ID关联。
2)一对一单向关联
执行插入测试方法:
Hibernate生成的sql语句如下:
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into t_user (name, id) values (?, ?)
Hibernate: insert into t_group (name, id) values (?, ?)
查询表里的数据:
SQL> select * from t_user;
ID NAME
---------- --------------------
280 csdner
SQL> select * from t_group;
ID NAME
---------- --------------------
280 developer
User对象和Group对象也有相同的ID,但是由于是单向的,只能通过Group对象查找对应的User对象。
(2)其中一个实体通过外键关联到另一个实体的主键。注:一对一,则外键必须为唯一约束
通过@JoinColumn注解定义一对一的关联关系。如果没有@JoinColumn注解,则系统自动处理,在主表中将创建连接列,列名为:主题的关联属性名 + 下划线 + 被关联端的主键列名。
执行插入测试代码:
Hibernate生成的sql语句如下:
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into t_group (name, id) values (?, ?)
Hibernate: insert into t_user (gp_id, name, id) values (?, ?, ?)
查询表里的数据:
SQL> select * from t_user;
ID NAME GP_ID
---------- -------------------- ----------
287 csdner 288
SQL> select * from t_group;
ID NAME
---------- --------------------
288 developer
User对象通过group_id 列关联Group对象
(3)通过关联表来保存两个实体之间的关联关系。注:一对一,则关联表每个外键都必须是唯一约束
执行插入测试方法:
Hibernate生成的sql语句如下:
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into t_group (name, id) values (?, ?)
Hibernate: insert into t_user (name, id) values (?, ?)
Hibernate: insert into t_user_group (group_id, user_id) values (?, ?)
查询表里的数据:
SQL> select * from t_user;
ID NAME
---------- --------------------
313 csdner
SQL> select * from t_group;
ID NAME
---------- --------------------
314 developer
SQL> select * from t_user_group;
USER_ID GROUP_ID
---------- ----------
313 314
2、一对多
一对多关联包括两种形式:单向一对多关联、双向一对多关联
单向一对多关联只需在“一”方进行配置(onetomany),即通过“一”关联到“多”。双向一对多需要关联双方均加以配置,这样既能通过“一”关联其对应的“多”,也可以通过“多”关联其对应的“一”。以用户TUser和地址TAddress做演示
单向一对多:只在TUser类中维护@OneToMany
测试方法:
对应的Hibernate生成的sql语句如下:
Hibernate: insert into cui_user (name, id) values (?, ?)
Hibernate: insert into cui_addr (addr, zip_code, id) values (?, ?, ?)
Hibernate: insert into cui_addr (addr, zip_code, id) values (?, ?, ?)
Hibernate: update cui_addr set user_id=? where id=?
Hibernate: update cui_addr set user_id=? where id=?
可见单向一对多中Hibernate是先插入TAddress记录,然后再维护关联关系字段user_id.
双向一对多:在TUser类中维护@OneToMany,在TAddress类中维护@ManyToOne
测试代码:
对应的Hibernate生成的sql语句如下:
Hibernate: insert into cui_user (name, id) values (?, ?)
Hibernate: insert into cui_addr (addr, user_id, zip_code, id) values (?, ?, ?, ?)
Hibernate: insert into cui_addr (addr, user_id, zip_code, id) values (?, ?, ?, ?)
可见在双向一对多关联中在新增TAddress记录时直接将关联字段user_id填充了,相比单向一对多少了两条更新语句。
3、多对多
示例:角色Role、权限Privilege
测试方法:
对应的Hibernate生成的sql语句如下:
Hibernate: insert into t_privilege (name, id) values (?, ?)
Hibernate: insert into t_privilege (name, id) values (?, ?)
Hibernate: insert into t_role (name, id) values (?, ?)
Hibernate: insert into t_role (name, id) values (?, ?)
Hibernate: insert into t_role_privilege (role_id, privilege_id) values (?, ?)
Hibernate: insert into t_role_privilege (role_id, privilege_id) values (?, ?)
Hibernate: insert into t_role_privilege (role_id, privilege_id) values (?, ?)