多对多关联关系

#单向多对多关联关系

2张表,这个时候需要第三章表来表示多对多关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Category {
private Integer id;
private String name;

//单向多对多这里有个集合用来保存item对象。
private Set<Item> items = new HashSet<Item>();

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Set<Item> getItems() {
return items;
}

public void setItems(Set<Item> items) {
this.items = items;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Item {    
private Integer id;
private String name;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<hibernate-mapping package="com.mamh.hibernate.demo.entities">

<class name="Category" table="hb_category" schema="mage">
<id name="id">
<column name="hb_id"/>
<generator class="native"/>
</id>
<property name="name" type="string">
<column name="hb_name"/>
</property>

<set name="items" table="hb_category_item" ><!--"hb_category_item"是中间表 -->
<key><column name="hb_category_id"/></key>

<!-- 使用manay to many 指定多对多关联关系。
column是执行set集合中的持久化类在中间表的外键列名。-->
<many-to-many class="Item" column="hb_item_id"/>



</class>
</hibernate-mapping>
1
2
3
4
5
6
7
8
9
10
11
12
13
<hibernate-mapping package="com.mamh.hibernate.demo.entities">

<class name="Item" table="hb_item" schema="mage">
<id name="id">
<column name="hb_id"/>
<generator class="native"/>
</id>
<property name="name" type="string">
<column name="hb_name"/>
</property>

</class>
</hibernate-mapping>

插入操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Test
public void testSaveCategory() {
Category category1 = new Category();
category1.setName("c-aa");
Category category2 = new Category();
category2.setName("c-bb");

Item item1 = new Item();
item1.setName("item-aa");
Item item2 = new Item();
item2.setName("item-aa");

category1.getItems().add(item1);
category1.getItems().add(item2);
category2.getItems().add(item1);
category2.getItems().add(item2);

session.save(category1);
session.save(category2);
session.save(item1);
session.save(item2);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Hibernate:     
insert into mage.hb_category (hb_name) values (?)
Hibernate:
insert into mage.hb_category (hb_name) values (?)
Hibernate:
insert into mage.hb_item (hb_name) values (?)
Hibernate:
insert into mage.hb_item (hb_name) values(?)
=destroy=
Hibernate:
insert into hb_category_item (hb_category_id, hb_item_id) values (?, ?)
Hibernate:
insert into hb_category_item (hb_category_id, hb_item_id) values (?, ?)
Hibernate:
insert into hb_category_item (hb_category_id, hb_item_id) values (?, ?)
Hibernate:
insert into hb_category_item (hb_category_id, hb_item_id) values (?, ?)

Process finished with exit code 0

插入操作时候,显示4个category,item的那四个insert 语句,后面还会有4个插入中间表的4条insert语句。


查询操作

1
2
3
4
5
@Test
public void testGetCategory(){
Category category = (Category) session.get(Category.class, 1);
System.out.println(category.getName());
}
1
2
3
4
5
6
7
8
9
10
11
12
Hibernate:     
select
category0_.hb_id as hb1_6_0_,
category0_.hb_name as hb2_6_0_
from
mage.hb_category category0_
where
category0_.hb_id=?
c-aa
=destroy=

Process finished with exit code 0

查询操作我们发现如果只是查询category的话,item是不会取查询的,懒加载。

1
2
3
4
5
6
7
@Test
public void testGetCategory(){
Category category = (Category) session.get(Category.class, 1);
System.out.println(category.getName());

System.out.println(category.getItems().size());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Hibernate:     
select
category0_.hb_id as hb1_6_0_,
category0_.hb_name as hb2_6_0_
from
mage.hb_category category0_
where
category0_.hb_id=?
c-aa
Hibernate:
select
items0_.hb_category_id as hb1_6_1_,
items0_.hb_item_id as hb2_1_,
item1_.hb_id as hb1_8_0_,
item1_.hb_name as hb2_8_0_
from
hb_category_item items0_
inner join
mage.hb_item item1_
on items0_.hb_item_id=item1_.hb_id
where
items0_.hb_category_id=?
2
=destroy=

Process finished with exit code 0

这个时候如果取访问 category中的items集合的话就会连带查询item表了。
使用了inner join内联的方式来关联中间表。

以上是单向的多对多关联关系。


#双向多对多关联关系

双向关联关系就是在Item类中也加一个集合,来保存category的引用。
原来的category类保持不变。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Item {    
private Integer id;
private String name;

private Set<Category> categories = new HashSet<Category>();

public Set<Category> getCategories() {
return categories;
}

public void setCategories(Set<Category> categories) {
this.categories = categories;
}

然后是item.hbm.xml 中也设置一个set属性,和category正好是相对的。

1
2
3
4
5
6
7
    
<set name="categories" table="hb_category_item">
<key>
<column name="hb_item_id"/>
</key>
<many-to-many class="Category" column="hb_category_id"/>
</set>

这个时候双向的需要在任意一端 的set中设置一个inverse = true,只让一端来维护关联关系。

1
2
3
4
5
6
7
8
9

<set name="items" table="hb_category_item" inverse="true">
<key>
<column name="hb_category_id"/>
</key>
<!-- 使用manay to many 指定多对多关联关系。
column是执行set集合中的持久化类在中间表的外键列名。 hb_item_id是中间表的列名。-->
<many-to-many class="Item" column="hb_item_id"/>
</set>

插入操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Test
public void testSaveCategory() {
Category category1 = new Category();
category1.setName("c-aa");
Category category2 = new Category();
category2.setName("c-bb");

Item item1 = new Item();
item1.setName("item-aa");
Item item2 = new Item();
item2.setName("item-aa");

category1.getItems().add(item1);
category1.getItems().add(item2);

category2.getItems().add(item1);
category2.getItems().add(item2);

item1.getCategories().add(category1);
item1.getCategories().add(category2);

item2.getCategories().add(category1);
item2.getCategories().add(category2);

session.save(category1);
session.save(category2);
session.save(item1);
session.save(item2);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Hibernate: 
insert into atguigu.hb_category (hb_name) values (?)
Hibernate:
insert into atguigu.hb_category (hb_name) values (?)
Hibernate:
insert into atguigu.hb_item (hb_name) values (?)
Hibernate:
insert into atguigu.hb_item (hb_name) values (?)
=destroy=
Hibernate:
insert into hb_category_item (hb_item_id, hb_category_id) values (?, ?)
Hibernate:
insert into hb_category_item (hb_item_id, hb_category_id) values (?, ?)
Hibernate:
insert into hb_category_item (hb_item_id, hb_category_id) values (?, ?)
Hibernate:
insert into hb_category_item (hb_item_id, hb_category_id) values (?, ?)

Process finished with exit code 0

category表格

#category表格 hb_id hb_name
1 1 c-aa
2 2 c-bb

item表格

#item表格 hb_id hb_name
1 1 item-aa
2 2 item-aa
中间表
#中间表 hb_category_id hb_item_id
-
1 1 1
2 1 2
3 2 1
4 2 2