[原创]java WEB学习笔记86:Hibernate学习之路-- -映射 n-n 关系,单向n-n,双向n-n
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用
内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系。
本人互联网技术爱好者,互联网技术发烧友
微博:伊直都在0221
QQ:951226918
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1.单向 n-n
域模型:
关系数据模型
2.解决方法
1)n-n 的关联必须使用连接表
2)与 1-n 映射类似,必须为 set 集合元素添加 key 子元素,指定 CATEGORIES_ITEMS 表中参照 CATEGORIES 表的外键为 CATEGORIY_ID.
3)与 1-n 关联映射不同的是,建立 n-n 关联时, 集合中的元素使用 many-to-many. many-to-many 子元素的 class 属性指定 items 集合中存放的是 Item 对象 , column 属性指定 CATEGORIES_ITEMS 表中参照 ITEMS 表的外键为 ITEM_ID
1 <!-- table:指定中间表 -->
2 <set name="items" table="CATEGORYS_ITEMS" >
3 <key>
4 <column name="C_ID" />
5 </key>
6 <!-- 使用 many-to-many 指定多对多的关联关系,column 指定 set集合中的 持久化类 在中间表的外键列的名称 -->
7 <many-to-many class="Item">
8 <column name="I_ID"></column>
9 </many-to-many>
10 </set>
3.代码
Category
1 package com.jason.hibernate.n2n;
2
3 import java.util.HashSet;
4 import java.util.Set;
5
6 public class Category {
7
8 private Integer id;
9 private String name;
10
11 private Set<Item> items = new HashSet<>();
12
13 public Integer getId() {
14 return id;
15 }
16
17 public void setId(Integer id) {
18 this.id = id;
19 }
20
21 public String getName() {
22 return name;
23 }
24
25 public void setName(String name) {
26 this.name = name;
27 }
28
29 public Set<Item> getItems() {
30 return items;
31 }
32
33 public void setItems(Set<Item> items) {
34 this.items = items;
35 }
36
37 }
Item
1 package com.jason.hibernate.n2n;
2
3 public class Item {
4
5 private Integer id;
6 private String name;
7
8 public Integer getId() {
9 return id;
10 }
11
12 public void setId(Integer id) {
13 this.id = id;
14 }
15
16 public String getName() {
17 return name;
18 }
19
20 public void setName(String name) {
21 this.name = name;
22 }
23
24 }
Category.hbm.xml
1 <?xml version="1.0"?>
2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
4
5 <hibernate-mapping package="com.jason.hibernate.n2n">
6
7 <class name="Category" table="CATEGORYS">
8
9 <id name="id" type="java.lang.Integer">
10 <column name="ID" />
11 <generator class="native" />
12 </id>
13
14 <property name="name" type="java.lang.String">
15 <column name="NAME" />
16 </property>
17
18
19 <!-- table:指定中间表 -->
20 <set name="items" table="CATEGORYS_ITEMS" >
21 <key>
22 <column name="C_ID" />
23 </key>
24 <!-- 使用 many-to-many 指定多对多的关联关系,column 指定 set集合中的 持久化类 在中间表的外键列的名称 -->
25 <many-to-many class="Item">
26 <column name="I_ID"></column>
27 </many-to-many>
28 </set>
29
30 </class>
31
32 </hibernate-mapping>
Item.hbm.xml
1 <?xml version="1.0"?>
2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
4
5
6 <hibernate-mapping>
7
8 <class name="com.jason.hibernate.n2n.Item" table="ITEMS">
9
10 <id name="id" type="java.lang.Integer">
11 <column name="ID" />
12 <generator class="native" />
13 </id>
14
15 <property name="name" type="java.lang.String">
16 <column name="NAME" />
17 </property>
18
19 </class>
20
21 </hibernate-mapping>
HibernateTest
1 package com.jason.hibernate.n2n;
2
3 import java.util.Date;
4 import java.util.Set;
5
6 import org.hibernate.Hibernate;
7 import org.hibernate.Session;
8 import org.hibernate.SessionFactory;
9 import org.hibernate.Transaction;
10 import org.hibernate.cfg.Configuration;
11 import org.hibernate.service.ServiceRegistry;
12 import org.hibernate.service.ServiceRegistryBuilder;
13 import org.junit.After;
14 import org.junit.Before;
15 import org.junit.Test;
16
17 public class HibernateTest {
18
19 private SessionFactory sessionFactory;
20 private Session session;
21 private Transaction transaction;
22
23
24 // 创建上述三个对象
25 @Before
26 public void init() {
27 Configuration configuration = new Configuration().configure();
28 ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
29 .applySettings(configuration.getProperties())
30 .buildServiceRegistry();
31
32 sessionFactory = configuration.buildSessionFactory(serviceRegistry);
33
34 session = sessionFactory.openSession();
35
36 transaction = session.beginTransaction();
37 }
38
39 // 关闭上述三个对象
40 @After
41 public void destroy() {
42 transaction.commit();
43 session.close();
44 sessionFactory.close();
45 }
46
47
48
49 @Test
50 public void testSave(){
51
52 Category category1 = new Category();
53 category1.setName("C-AA");
54
55 Category category2 = new Category();
56 category2.setName("C-BB");
57
58 Item item1 = new Item();
59 item1.setName("I-AA");
60
61 Item item2 = new Item();
62 item2.setName("I-BB");
63
64 //设定关联关系
65 category1.getItems().add(item1);
66 category1.getItems().add(item2);
67
68
69 category2.getItems().add(item1);
70 category2.getItems().add(item2);
71
72
73 session.save(category1);
74 session.save(category2);
75
76 session.save(item1);
77 session.save(item2);
78
79 }
80
81
82 @Test
83 public void testGet(){
84
85 Category category = (Category) session.get(Category.class, 1);
86 System.out.println(category.getName());
87
88 //需要拦截中间表
89 Set<Item> items = category.getItems();
90 System.out.println(items.size());
91
92 }
93
94
95
96
97 }
hibernate.cfg.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE hibernate-configuration PUBLIC
3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
4 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
5 <hibernate-configuration>
6 <session-factory>
7 <!-- hibernate 连接数据库的基本信息 -->
8 <property name="connection.username">root</property>
9 <property name="connection.password">zhangzhen</property>
10 <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
11 <property name="connection.url">jdbc:mysql:///hibernate</property>
12
13
14 <!-- 配置hibernate 的节本信息 -->
15 <!-- hibernate 所使用的数据库方言 -->
16 <!--<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>-->
17 <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
18 <!-- 执行操作时是否在控制台打印SQL -->
19 <property name="show_sql">true</property>
20
21 <!-- 是否都SQL 进行格式化 -->
22 <property name="format_sql">true</property>
23
24
25 <!-- 指定自动生成数据表的策略 -->
26 <property name="hbm2ddl.auto">update</property>
27
28 <!-- 设置hibernate 的事务隔离级别 -->
29 <property name="connection.isolation">2</property>
30
31
32 <!-- 配置c3p0 -->
33 <property name="hibernate.c3p0.max_size">10</property>
34 <property name="hibernate.c3p0.min_size">5</property>
35 <property name="c3p0.acquire_increment">2</property>
36 <property name="c3p0.idle_test_period">2000</property>
37 <property name="c3p0.timeout">2000</property>
38 <property name="c3p0.max_statements">10</property>
39
40
41 <!-- 对于mysql 无效,对于oracle 有效 -->
42 <!-- 设定JDBC 的Statement 读取数据的时候每次从数据库中取出的记录的条数 -->
43 <property name="hibernate.jdbc.fetch_size">100</property>
44
45 <!-- 设置数据库进行批量删除,批量更新和批量插入的时候的大小 -->
46 <property name="hibernate.jdbc.batch_size">30</property>
47 <mapping resource="com/jason/hibernate/n2n/Category.hbm.xml"/>
48 <mapping resource="com/jason/hibernate/n2n/Item.hbm.xml"/>
49
50
51 </session-factory>
52
53 </hibernate-configuration>
4.双向n-n
域模型:
关系数据模型
1)核心点
① 双向 n-n 关联需要两端都使用集合属性
② 双向n-n关联必须使用连接表
③ 集合属性应增加 key 子元素用以映射外键列, 集合元素里还应增加many-to-many子元素关联实体类
④ 在双向 n-n 关联的两边都需指定连接表的表名及外键列的列名. 两个集合元素 set 的 table 元素的值必须指定,而且必须相同。
set元素的两个子元素:key 和 many-to-many 都必须指定 column 属性,其中,
key 和 many-to-many 分别指定本持久化类和关联类在连接表中的外键列名,因此两边的 key 与 many-to-many 的column属性交叉相同。
也就是说,一边的set元素的key的 cloumn值为a,many-to-many 的 column 为b;则另一边的 set 元素的 key 的 column 值 b,many-to-many的 column 值为 a.
⑥ 对于双向 n-n 关联, 必须把其中一端的 inverse 设置为 true, 否则两端都维护关联关系可能会造成主键冲突.
Catogery
1 package com.jason.hibernate.n2n;
2
3 import java.util.HashSet;
4 import java.util.Set;
5
6 public class Category {
7
8 private Integer id;
9 private String name;
10
11 private Set<Item> items = new HashSet<>();
12
13 public Integer getId() {
14 return id;
15 }
16
17 public void setId(Integer id) {
18 this.id = id;
19 }
20
21 public String getName() {
22 return name;
23 }
24
25 public void setName(String name) {
26 this.name = name;
27 }
28
29 public Set<Item> getItems() {
30 return items;
31 }
32
33 public void setItems(Set<Item> items) {
34 this.items = items;
35 }
36
37 }
Item
1 package com.jason.hibernate.n2n;
2
3 import java.util.HashSet;
4 import java.util.Set;
5
6 public class Item {
7
8 private Integer id;
9 private String name;
10
11 private Set<Category> categories = new HashSet<>();
12
13 public Set<Category> getCategories() {
14 return categories;
15 }
16
17 public void setCategories(Set<Category> categories) {
18 this.categories = categories;
19 }
20
21 public Integer getId() {
22 return id;
23 }
24
25 public void setId(Integer id) {
26 this.id = id;
27 }
28
29 public String getName() {
30 return name;
31 }
32
33 public void setName(String name) {
34 this.name = name;
35 }
36
37 }
Category.hbm.xml
1 <?xml version="1.0"?>
2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
4
5 <hibernate-mapping package="com.jason.hibernate.n2n">
6
7 <class name="Category" table="CATEGORYS">
8
9 <id name="id" type="java.lang.Integer">
10 <column name="ID" />
11 <generator class="native" />
12 </id>
13
14 <property name="name" type="java.lang.String">
15 <column name="NAME" />
16 </property>
17
18
19 <!-- table:指定中间表 -->
20 <set name="items" table="CATEGORYS_ITEMS" >
21 <key>
22 <column name="C_ID" />
23 </key>
24 <!-- 使用 many-to-many 指定多对多的关联关系,column 指定 set集合中的 持久化类 在中间表的外键列的名称 -->
25 <many-to-many class="Item">
26 <column name="I_ID"></column>
27 </many-to-many>
28 </set>
29
30 </class>
31
32 </hibernate-mapping>
Item.hbm.xml
1 <?xml version="1.0"?>
2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
4
5
6 <hibernate-mapping>
7
8 <class name="com.jason.hibernate.n2n.Item" table="ITEMS">
9
10 <id name="id" type="java.lang.Integer">
11 <column name="ID" />
12 <generator class="native" />
13 </id>
14
15 <property name="name" type="java.lang.String">
16 <column name="NAME" />
17 </property>
18
19
20
21 <set name="categories" table="CATEGORYS_ITEMS">
22 <key column="I_ID"></key>
23 <many-to-many class="com.jason.hibernate.n2n.Category">
24 <column name="C_ID"></column>
25 </many-to-many>
26 </set>
27
28
29
30 </class>
31
32 </hibernate-mapping>
hibernate.cfg.xml
hibernateTest