`
刘小小尘
  • 浏览: 62757 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

hibernate映射关系

 
阅读更多

以简单的两个类为例:
User(int id, String name)
Group(int id, String name)

没有关联关系时的关系模型:
t_user(id int pk, name varchar)
t_group(id int pk, name varchar)

一、多对一和一对多关联映射(多个用户有相同的组)

这几种关联映射后的关系模型是相同的:
t_user(id int pk, name varchar,
gid int fk->t_group(id))
t_group(id int pk, name varchar)

1、多对一单向关联

实体模型:
bean.User(int id, String name,
Group group)
bean.Group(int id, String name)

view sourceprint?

01

<!-- bean/User.hbm.xml -->

02

03

<hibernate-mapping>

04

<class name="bean.User" table="t_user">

05

<id name="id"><generator class="native"/></id>

06

<property name="name"/>

07

<!-- 使用<many-to-one>映射多对一关系。导出ddl时将自动生成一个外键 -->

08

<many-to-one name="group" column="gid"/>

09

</class>

10

</hibernate-mapping>

view sourceprint?

1

<!-- bean/Group.hbm.xml -->

2

3

<hibernate-mapping>

4

<class name="bean.Group" table="t_group">

5

<id name="id"><generator class="native"/></id>

6

<property name="name"/>

7

</class>

8

</hibernate-mapping>

2、一对多单向关联(几乎不用)

实体模型:
bean.User(int id, String name)
bean.Group(int id, String name,
Set users)

view sourceprint?

1

<!-- bean/User.hbm.xml -->

2

3

<hibernate-mapping>

4

<class name="bean.User" table="t_user">

5

<id name="id"><generator class="native"/></id>

6

<property name="name"/>

7

</class>

8

</hibernate-mapping>

view sourceprint?

01

<!-- bean/Group.hbm.xml -->

02

03

<hibernate-mapping>

04

<class name="bean.Group" table="t_group">

05

<id name="id"><generator class="native"/></id>

06

<property name="name"/>

07

<!-- 使用<set>映射集合 -->

08

<set name="users">

09

<!-- 使用<key>指定引用至自身的外键表(t_user)中的外键 -->

10

<key column="gid"/>

11

<!-- 使用<one-to-many>映射一对多关系 -->

12

<one-to-many class="bean.User"/>

13

</set>

14

</class>

15

</hibernate-mapping>

Group加入集合也可以使用List<list>),注意不能指定类型是具体的HashSetArrayList,只能是接口SetList
集合标签可以使用order-by属性指定排序:

view sourceprint?

1

<set name="users" order-by="id desc">

3、双向关联

实体模型:
bean.User(int id, String name,
Group group)
bean.Group(int id, String name,
Set users)

view sourceprint?

01

<!-- bean/User.hbm.xml -->

02

03

<hibernate-mapping>

04

<class name="bean.User" table="t_user">

05

<id name="id"><generator class="native"/></id>

06

<property name="name"/>

07

<!-- 使用<many-to-one>映射多对一关系。导出ddl时将自动生成一个外键 -->

08

<many-to-one name="group" column="gid"/>

09

</class>

10

</hibernate-mapping>

view sourceprint?

01

<!-- bean/Group.hbm.xml -->

02

03

<hibernate-mapping>

04

<class name="bean.Group" table="t_group">

05

<id name="id"><generator class="native"/></id>

06

<property name="name"/>

07

<!-- 使用<set>映射集合 -->

08

<set name="users">

09

<!-- 使用<key>指定引用至自身的外键表(t_user)中的外键 -->

10

<key column="gid"/>

11

<!-- 使用<one-to-many>映射一对多关系 -->

12

<one-to-many class="bean.User"/>

13

</set>

14

</class>

15

</hibernate-mapping>

双向关联中,为<set>加入”inverse=true”可以反转维护关系:Hibernate将放弃从一的一端维护。意思就是usergroup的关系必须使用user维护,操作groupHibernate将不维护这个关系。

view sourceprint?

1

<set name="users" inverse="true">

操作group的示例:

view sourceprint?

01

session.beginTransaction();

02

User user = new User();

03

user.setName("张三");

04

05

Group group = new Group();

06

group.setName("admin");

07

group.setUsers(new HashSet());

08

group.getUsers().add(user);

09

10

session.save(user);

11

session.save(group);

12

session.getTransaction().commit();

没有配置inverse=”true”时,Hibernate输出了添加usergroup,并更新user的语句:

Hibernate: insert into t_user (name, gid) values (?, ?)

Hibernate: insert into t_group (name) values (?)

Hibernate: update t_user set gid=? where id=?

而配置了inverse=”true”后,Hibernate仅仅输出了添加usergroup的语句,并没有更新user,放弃了关系的维护:

Hibernate: insert into t_user (name, gid) values (?, ?)

Hibernate: insert into t_group (name) values (?)

此时应该从user端维护关系:

view sourceprint?

01

session.beginTransaction();

02

Group group = new Group();

03

group.setName("admin");

04

05

User user = new User();

06

user.setName("张三");

07

user.setGroup(group);

08

09

session.save(group);

10

session.save(user);

11

session.getTransaction().commit();

因为外键列在t_user表中,从group端维护需要操作多表,所以从user端维护关系更加合理,效率也更高。上面的代码输出两条SQL语句,插入数据的同时也维护了关系:

Hibernate: insert into t_group (name) values (?)

Hibernate: insert into t_user (name, gid) values (?, ?)

二、一对一关联映射(每个用户独有一个组)

依照映射方法不同,可分为主键关联映射唯一外键关联映射。主键关联是维护两张表的主键一致,如有必要还可以在主键上再加上外键约束;唯一外键关联则类似于多对一关联,为表加入一个外键列,不过一对一关联会同时将这个外键加上唯一约束。

1、主键关联映射

主键关联生成的关系模型:
t_user(id int pk
fk->t_group(id), name varchar)
t_group(id int pk, name varchar)

1.1、主键单向关联

实体模型:
bean.User(int id, String name,
Group group)
bean.Group(int id, String name)

view sourceprint?

01

<!-- bean/User.hbm.xml -->

02

03

<hibernate-mapping>

04

<class name="bean.User" table="t_user">

05

<id name="id">

06

<!-- 指定主键生成策略为外键 -->

07

<generator class="foreign">

08

<!-- 指定要参照的属性 -->

09

<param name="property">group</param>

10

</generator>

11

</id>

12

<property name="name"/>

13

<!-- 使用<one-to-one>映射一对一关系。 -->

14

<one-to-one name="group">

15

</class>

16

</hibernate-mapping>

view sourceprint?

1

<!-- bean/Group.hbm.xml -->

2

3

<hibernate-mapping>

4

<class name="bean.Group" table="t_group">

5

<id name="id"><generator class="native"/></id>

6

<property name="name"/>

7

</class>

8

</hibernate-mapping>

主键关联由Hibernate维护,不依赖数据库。如果需要在数据库端也生成外键约束,可以使用constrained

view sourceprint?

1

<one-to-one name="group" constrained="true"/>

1.2、主键双向关联

实体模型:
bean.User(int id, String name,
Group group)
bean.Group(int id, String name,
User user)

view sourceprint?

01

<!-- bean/User.hbm.xml -->

02

03

<hibernate-mapping>

04

<class name="bean.User" table="t_user">

05

<id name="id">

06

<!-- 指定主键生成策略为外键 -->

07

<generator class="foreign">

08

<!-- 指定要参照的属性 -->

09

<param name="property">group</param>

10

</generator>

11

</id>

12

<property name="name"/>

13

<!-- 使用<one-to-one>映射一对一关系。 -->

14

<one-to-one name="group">

15

</class>

16

</hibernate-mapping>

view sourceprint?

01

<!-- bean/Group.hbm.xml -->

02

03

<hibernate-mapping>

04

<class name="bean.Group" table="t_group">

05

<id name="id"><generator class="native"/></id>

06

<property name="name"/>

07

<!-- 使用<one-to-one>映射一对一关系 -->

08

<one-to-one name="user"/>

09

</class>

10

</hibernate-mapping>

2、唯一外键关联映射

唯一外键关联生成的关系模型:
t_user(id int pk, name varchar, gid int fk->t_group(id))
t_group(id int pk, name varchar)

2.1、唯一外键单向关联

实体模型:
bean.User(int id, String name,
Group group)
bean.Group(int id, String name)

view sourceprint?

01

<!-- bean/User.hbm.xml -->

02

03

<hibernate-mapping>

04

<class name="bean.User" table="t_user">

05

<id name="id">

06

<generator class="native"/>

07

</id>

08

<property name="name"/>

09

<!-- <many-to-one>加上unique就变成了一对一 -->

10

<many-to-one name="group" unique="true" column="gid"/>

11

</class>

12

</hibernate-mapping>

view sourceprint?

1

<!-- bean/Group.hbm.xml -->

2

3

<hibernate-mapping>

4

<class name="bean.Group" table="t_group">

5

<id name="id"><generator class="native"/></id>

6

<property name="name"/>

7

</class>

8

</hibernate-mapping>

2.2、唯一外键双向关联

实体模型:
bean.User(int id, String name,
Group group)
bean.Group(int id, String name,
User user)

view sourceprint?

01

<!-- bean/User.hbm.xml -->

02

03

<hibernate-mapping>

04

<class name="bean.User" table="t_user">

05

<id name="id">

06

<generator class="native"/>

07

</id>

08

<property name="name"/>

09

<!-- <many-to-one>加上unique就变成了一对一 -->

10

<many-to-one name="group" unique="true" column="gid"/>

11

</class>

12

</hibernate-mapping>

view sourceprint?

01

<!-- bean/Group.hbm.xml -->

02

03

<hibernate-mapping>

04

<class name="bean.Group" table="t_group">

05

<id name="id"><generator class="native"/></id>

06

<property name="name"/>

07

<!-- 使用<one-to-one>映射一对一 -->

08

<one-to-one name="user"/>

09

</class>

10

</hibernate-mapping>

三、多对多关联映射(每个用户拥有多个组,每个组也有多个用户)

多对多关联映射关系使用中间表表示。导出关系模型时Hibernate将自动生成复合主键以及外键约束。

关系模型:
t_user(id int pk, name varchar)
t_group(id int pk, name varchar)
t_user_group(userid int fk->t_user(id), groupid int fk->t_group(id), pk(userid, groupid))

1、多对多单向关联

实体模型:
bean.User(int id, String name,
Set groups)
bean.Group(int id, String name)

view sourceprint?

01

<!-- bean/User.hbm.xml -->

02

03

<hibernate-mapping>

04

<class name="bean.User" table="t_user">

05

<id name="id">

06

<generator class="native"/>

07

</id>

08

<property name="name"/>

09

<!-- 使用<set>映射集合,在多对多关系中,Hibernate将生成第三张表 -->

10

<set name="groups" table="t_user_group">

11

<!-- 使用<key>指定引用至自身的外键表(t_user_group)中的外键 -->

12

<key column="userid"/>

13

<!-- 使用<many-to-many>映射多对多关系,column指定另一端在表t_user_group中的列 -->

14

<many-to-many class="bean.Group" column="groupid"/>

15

</set>

16

</class>

17

</hibernate-mapping>

view sourceprint?

1

<!-- bean/Group.hbm.xml -->

2

3

<hibernate-mapping>

4

<class name="bean.Group" table="t_group">

5

<id name="id"><generator class="native"/></id>

6

<property name="name"/>

7

</class>

8

</hibernate-mapping>

1、多对多单向关联

实体模型:
bean.User(int id, String name,
Set groups)
bean.Group(int id, String name,
Set users)

view sourceprint?

01

<!-- bean/User.hbm.xml -->

02

03

<hibernate-mapping>

04

<class name="bean.User" table="t_user">

05

<id name="id">

06

<generator class="native"/>

07

</id>

08

<property name="name"/>

09

<!-- 使用<set>映射集合,在多对多关系中,Hibernate将生成第三张表 -->

10

<set name="groups" table="t_user_group">

11

<!-- 使用<key>指定引用至自身的外键表(t_user_group)中的外键 -->

12

<key column="userid"/>

13

<!-- 使用<many-to-many>映射多对多关系,column指定另一端在表t_user_group中的列 -->

14

<many-to-many class="bean.Group" column="groupid"/>

15

</set>

16

</class>

17

</hibernate-mapping>

view sourceprint?

01

<!-- bean/Group.hbm.xml -->

02

03

<hibernate-mapping>

04

<class name="bean.Group" table="t_group">

05

<id name="id">

06

<generator class="native"/>

07

</id>

08

<property name="name"/>

09

<!-- 使用<set>映射集合,在多对多关系中,Hibernate将生成第三张表 -->

10

<set name="users" table="t_user_group">

11

<!-- 使用<key>指定引用至自身的外键表(t_user_group)中的外键 -->

12

<key column="group"/>

13

<!-- 使用<many-to-many>映射多对多关系,column指定另一端在表t_user_group中的列 -->

14

<many-to-many class="bean.User" column="userid"/>

15

</set>

16

</class>

17

</hibernate-mapping>

多对多的双向关联同样可以在不想要维护关系的一端的<set>里设置inverse=”true”;但是必须有一端可以维护,也就是说只可以设置一个。

Technorati 标签: Java,Hibernate,学习笔记,映射,关联映射,Mapping

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics