今天心情好。。建了一个比笔记1那篇更简单的表来演示Foo程序:)
一。数据库格式
user表
address表
address表持有user_id外键,由此应该可以看出两张表表示的关系为: “1个用户可以拥有多个地址”
二。双向关联
下面生成POJO对象:
1. package
2.
3. /**
4. * Address entity.
5. *
6. * @author MyEclipse Persistence Tools
7. */
8.
9. public class Address implements
10.
11. // Fields
12.
13. private
14. private
15. private
16.
17. // Constructors
18.
19. /** default constructor */
20. public
21. }
22.
23. /** minimal constructor */
24. public
25. this.user = user;
26. }
27.
28. /** full constructor */
29. public
30. this.user = user;
31. this.addressDetail = addressDetail;
32. }
33.
34. // Property accessors
35.
36. public
37. return this.addressId;
38. }
39.
40. public void
41. this.addressId = addressId;
42. }
43.
44. public
45. return this.user;
46. }
47.
48. public void
49. this.user = user;
50. }
51.
52. public
53. return this.addressDetail;
54. }
55.
56. public void
57. this.addressDetail = addressDetail;
58. }
59.
60. }
由于是双向关联,因此生成的2个POJO对象都会持有对方对象。并且1对N中,1方持有N方Set集合,N方持有1方单个对象。
下面是生成的映射配置:
Address.hbm.xml
1. <?xml version="1.0" encoding="utf-8"?>
2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
4. <!--
5. Mapping file autogenerated by MyEclipse Persistence Tools
6. -->
7. <hibernate-mapping>
8. <class name="model.Address" table="address" catalog="email">
9. <id name="addressId" type="java.lang.Integer">
10. <column name="address_id" />
11. <generator class="identity" />
12. </id>
13. <many-to-one name="user" class="model.User" fetch="select">
14. <column name="user_id" not-null="true" />
15. </many-to-one>
16. <property name="addressDetail" type="java.lang.String">
17. <column name="address_detail" length="45" />
18. </property>
19. </class>
20. </hibernate-mapping>
User.hbm.xml
1.
2. <?xml version="1.0" encoding="utf-8"?>
3. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
5. <!--
6. Mapping file autogenerated by MyEclipse Persistence Tools
7. -->
8. <hibernate-mapping>
9. <class name="model.User" table="user" catalog="email">
10. <id name="userId" type="java.lang.Integer">
11. <column name="user_id" />
12. <generator class="identity" />
13. </id>
14. <property name="userName" type="java.lang.String">
15. <column name="user_name" length="45" not-null="true" />
16. </property>
17. <set name="addresses" inverse="true">
18. <key>
19. <column name="user_id" not-null="true" />
20. </key>
21. <one-to-many class="model.Address" />
22. </set>
23. </class>
24. </hibernate-mapping>
双向1:N关系基本配置很容易套格式,要注意的是在1方配置inverse="true",意思就是将控制方向交给N方会比较高效一点:)。具体后面解释inverse的概念。
下面是一个简单的TestCase,演示保存操作:)
1. import
2. import
3.
4. import
5. import
6.
7. import
8. import
9. import
10. import
11. import
12. import
13.
14. public class
15.
16. null;
17.
18. @Before
19. // 读取classpath下的配置文件hibernate.cfg.xml
20. // current_session_context_class=thread,show_sql=true
21. public void
22. try
23. new
24. SessionFactory sf = cfg.buildSessionFactory();
25. session = sf.getCurrentSession();
26. catch
27. e.printStackTrace();
28. }
29. }
30.
31. @Test
32. public void
33. session.beginTransaction();
34. new
35. "hello");
36.
37. //new Address
38. new
39. "luoyu road 1037#");
40. u.getAddresses().add(add);
41.
42. session.save(u);
43. session.getTransaction().commit();
44. }
45. }
BothSide()方法中创建了一个User,一个Address,然后save,run一下用例,查看到Hibernate执行了下面的操作:
insert into user (user_name) values (?)
只保存了user,如果目的就是象方法所写 save(u),那么就是对的。但是更新了User的同时也想保存这个Address怎么办?
想同时保存User和Address,需要做如下两处修改:
1.在User.hbm.xml 17行写上cascade="all"(对User的所有操作均级联到Address表上)
2.在BothSide() 39-40行中添加 add.setUser(u); (由于address的user_id外键字段不需为空,不给它赋值就会报错)
具体见下:
User.hbm.xml
1. <?xml version="1.0" encoding="utf-8"?>
2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
4. <!--
5. Mapping file autogenerated by MyEclipse Persistence Tools
6. -->
7. <hibernate-mapping>
8. class name="model.User" table="user" catalog="email">
9. "userId" type="java.lang.Integer">
10. "user_id"
11. class="identity"
12. </id>
13. "userName" type="java.lang.String">
14. "user_name" length="45" not-null="true"
15. </property>
16. "addresses" inverse="true" cascade="all">
17. <key>
18. "user_id" not-null="true"
19. </key>
20. class="model.Address"
21. </set>
22. class>
23. </hibernate-mapping
1. @Test
2. public void
3. session.beginTransaction();
4. new
5. "hello");
6.
7. //new Address
8. new
9. "luoyu road 1037#");
10. add.setUser(u);
11. //add Address to user
12. u.getAddresses().add(add);
13.
14. session.save(u);
15. session.getTransaction().commit();
16. }
上面这段代码之所以需要添加add.setUser(u),最根本的原因就是上面提到的:我在在User方配置了inverse=true.意思就是“双方的关系交给Address你来管理,User我不负责维护关系”,因此User也不会主动去填充Address方的user_id.
然而,在维护关系的Address一方,我们访问每一个Address对象的时候,都可以获取到User对象.