今天心情好。。建了一个比笔记1那篇更简单的表来演示Foo程序:)

 

一。数据库格式

user表

Hibernate笔记2--映射对象之间的关系_encoding

address表

Hibernate笔记2--映射对象之间的关系_user_02

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对象.