hibernate中雙向關(guān)聯(lián)在級(jí)聯(lián)情況下save對(duì)象討論_第1頁
hibernate中雙向關(guān)聯(lián)在級(jí)聯(lián)情況下save對(duì)象討論_第2頁
hibernate中雙向關(guān)聯(lián)在級(jí)聯(lián)情況下save對(duì)象討論_第3頁
hibernate中雙向關(guān)聯(lián)在級(jí)聯(lián)情況下save對(duì)象討論_第4頁
hibernate中雙向關(guān)聯(lián)在級(jí)聯(lián)情況下save對(duì)象討論_第5頁
已閱讀5頁,還剩10頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、hibernate中雙向關(guān)聯(lián)在級(jí)聯(lián)情況下save對(duì)象討論一般在雙向關(guān)聯(lián)的情況下,都要在一方設(shè)置mappedBy(name="xxx"),由對(duì)方主導(dǎo)映射關(guān)系。在多對(duì)一的情況下,一般在多的一方設(shè)置主導(dǎo)映射的關(guān)系(為了方便敘述,就這么叫它了,呵呵)。所謂主導(dǎo)這種映射關(guān)系,如group,user,就是由多的一方(user)里面產(chǎn)生一個(gè)外鍵參考一的一方(group)的主鍵,這時(shí)候user就是主導(dǎo)的一方,寫mappedBy是被主導(dǎo)的一方。在多對(duì)多的情況下,隨便由那方主導(dǎo),在數(shù)據(jù)庫表的結(jié)構(gòu)上都是一樣的,都會(huì)產(chǎn)生一個(gè)中間表,中間表有兩個(gè)字段的聯(lián)合主鍵,分別作為外鍵參考兩個(gè)多的一方。在一對(duì)多

2、和多對(duì)多的雙向關(guān)聯(lián)的情況下,并且在cascade=CascadeType.ALL情況下,save不同方面(如主導(dǎo)關(guān)系一方或被主導(dǎo)的一方)在級(jí)聯(lián)的具體表現(xiàn)上是不同的。分別來討論一下。先看一對(duì)多的雙向關(guān)聯(lián)關(guān)系,這里就拿group和user舉例。Group類如下:java view plain copy1. package com.chen.hibernate.ormapping;  2.   3. import java.util.HashSet;  4. import java.util

3、.Set;  5.   6. import javax.persistence.CascadeType;  7. import javax.persistence.Entity;  8. import javax.persistence.FetchType;  9. import javax.persistence.GeneratedValue;  10. import javax.persistence.Id; &

4、#160;11. import javax.persistence.OneToMany;  12. import javax.persistence.Table;  13.   14. Entity  15. Table(name = "t_group")  16. public class Group   17.     private 

5、;int id;  18.     private String name;  19.     private Set<User> users = new HashSet<User>();  20.   21.     Id  22.    &#

6、160;GeneratedValue  23.     public int getId()   24.         return id;  25.       26.   27.     public void setId(int&#

7、160;id)   28.         this.id = id;  29.       30.   31.     public String getName()   32.         r

8、eturn name;  33.       34.   35.     public void setName(String name)   36.          = name;  37.     

9、0; 38.   39.     / 設(shè)置mappedBy是被主導(dǎo)的一方   40.     OneToMany(mappedBy = "group", cascade =  CascadeType.ALL , fetch = FetchType.LAZY)  41.    &#

10、160;public Set<User> getUsers()   42.         return users;  43.       44.   45.     public void setUsers(Set<User> users)  

11、; 46.         this.users = users;  47.       48.   User類如下:java view plain copy1. package com.chen.hibernate.ormapping;  2.   3. import javax.persistence.C

12、ascadeType;  4. import javax.persistence.Entity;  5. import javax.persistence.FetchType;  6. import javax.persistence.GeneratedValue;  7. import javax.persistence.Id;  8. import javax.persistence.JoinColumn;  9. imp

13、ort javax.persistence.ManyToOne;  10. import javax.persistence.Table;  11.   12. Entity  13. Table(name = "t_user")  14. public class User   15.     private int id;&

14、#160; 16.     private String name;  17.     private Group group;  18.   19.     Id  20.     GeneratedValue  21.     public

15、60;int getId()   22.         return id;  23.       24.   25.     public void setId(int id)   26.       &#

16、160; this.id = id;  27.       28.   29.     public String getName()   30.         return name;  31.       

17、;32.   33.     public void setName(String name)   34.          = name;  35.       36.   37.     /設(shè)置fetch為lazy,多

18、的一方默認(rèn)問eager  38.     ManyToOne(cascade =  CascadeType.ALL , fetch = FetchType.EAGER)  39.     JoinColumn(name = "groupId")  40.     public Group 

19、getGroup()   41.         return group;  42.       43.   44.     public void setGroup(Group group)   45.       

20、  this.group = group;  46.       47.   junit測(cè)試類java view plain copy1. package com.chen.hibernate.ormapping;  2.   3. import org.hibernate.Session;  4. import org.hibernate.Ses

21、sionFactory;  5. import org.hibernate.cfg.AnnotationConfiguration;  6. import org.hibernate.tool.hbm2ddl.SchemaExport;  7. import org.junit.AfterClass;  8. import org.junit.BeforeClass;  9. import org.junit.Test;  1

22、0.   11. public class CRUDTest   12.     private static SessionFactory sessionFactory = null;  13.   14.     BeforeClass  15.     public static&#

23、160;void beforeClass()   16.         new SchemaExport(new AnnotationConfiguration().configure().create(  17.                 false, tru

24、e);  18.         sessionFactory = new AnnotationConfiguration().configure()  19.                 .buildSessionFactory();  20.  

25、60;    21.   22.     Test  23.     public void testSaveUser()   24.         User user = new User();  25.    &#

26、160;    user.setName("u1");  26.         Group group = new Group();  27.         group.setName("g1");  28.   29.  &

27、#160;      / 這里僅僅把group加到user中,而不需要group.getUsers().add(user);把當(dāng)前的對(duì)象加入到group的set里  30.         user.setGroup(group);  31.   32.         Session sessio

28、n = sessionFactory.getCurrentSession();  33.         session.beginTransaction();  34.         session.save(user);  35.         session.getTr

29、ansaction().commit();  36.       37.   38.     / 再看看save被主導(dǎo)的一方會(huì)如何。  39.     Test  40.     public void testSaveGroup()   41.   

30、0;     / 先new兩個(gè)user,一個(gè)group,然后把user加到group中  42.         User user = new User();  43.         user.setName("u1");  44.   

31、;45.         User user2 = new User();  46.         user2.setName("u2");  47.         Group group = new Group()

32、;  48.         group.setName("g1");  49.         group.getUsers().add(user);  50.         group.getUsers().add(user2);  51.  

33、 52.         / 注意,雖然兩邊都是級(jí)聯(lián)的方式,但這裡的user也要把group設(shè)一下,不然,save(group)的時(shí)候,user表中的  53.         / groupId字段仍是null  54.         user.setGroup(group);

34、0; 55.         user2.setGroup(group);  56.   57.         Session session = sessionFactory.getCurrentSession();  58.         sessio

35、n.beginTransaction();  59.           60.         /* 61.          * 此時(shí)在save(group)的時(shí)候,由于級(jí)聯(lián)關(guān)系會(huì)先插入里面的兩個(gè)user,而此時(shí)如果不寫上面的 62.    &#

36、160;     * user.setGroup(group); user2.setGroup(group); 63.          * 這兩句,user對(duì)應(yīng)表里面的groupId字段都將為空 64.          */  65.      

37、   session.save(group);  66.         session.getTransaction().commit();  67.       68.   69.     AfterClass  70.     public static

38、 void afterClass()   71.         sessionFactory.close();  72.       73.   74.   先來個(gè)結(jié)論,什么時(shí)候t_user中的外鍵groupId才會(huì)參考t_group主鍵取得值?結(jié)論:這里的關(guān)系的主導(dǎo)方向是User->Group,只有當(dāng)級(jí)聯(lián)的方向也是從User->Gr

39、oup時(shí),才會(huì)設(shè)置這個(gè)外鍵的值。這個(gè)結(jié)論可以參考這樣的圖:看下實(shí)驗(yàn)結(jié)果,先測(cè)試運(yùn)行testSaveUser方法,運(yùn)行結(jié)果對(duì)于的t_group和t_user表如下,此時(shí)數(shù)據(jù)插入都是正常的。插入的過程是應(yīng)該是這樣的,由于save的是user,所以先插t_user表,由于t_user表和t_group表的主鍵id字段都是由同一個(gè)sequence產(chǎn)生的,所以這里由主鍵id字段也可以看出先是插入了t_user,t_user中有g(shù)roup對(duì)象且不是null(要是null的話,即使設(shè)了級(jí)聯(lián),也不會(huì)再插t_group表了,沒東西插入?。。?,由于User設(shè)置了級(jí)聯(lián),所以此時(shí)又插入了t_group表,因?yàn)榧?jí)聯(lián)的方

40、向?yàn)閁ser->Group,和關(guān)系的主導(dǎo)方向相同,所以這里t_user表的groupId字段參考了t_group表的主鍵字段2。t_user表t_group表在測(cè)試下testSaveGroup,若先注掉user.setGroup(group);user2.setGroup(group);這兩行,也就是說就像testSaveUser中一樣,只是簡(jiǎn)單的把user加到group里的集合set里,會(huì)怎樣呢?測(cè)試的結(jié)果如下:t_user表t_group表可以看到t_user表的groupId字段為空,為什么呢?同樣按照上面的分析思路,由于save的是group,所以先插入t_group表,插入1,

41、g1,而group對(duì)象中有一個(gè)user的集合,里面有兩個(gè)user,由于級(jí)聯(lián),此時(shí)就會(huì)插入t_user表,此時(shí)級(jí)聯(lián)的方向?yàn)镚roup->User,這個(gè)級(jí)聯(lián)方向不會(huì)設(shè)置t_user中的groupId,因?yàn)樯厦孀⑨尩袅藆ser.setGroup(group);user2.setGroup(group);這兩句,也就是說這兩個(gè)user中的group都為null,所以在插入t_user表的時(shí)候不會(huì)產(chǎn)生級(jí)聯(lián)再插入t_group表了,所以t_user中兩條記錄的groupId字段都為空。把user.setGroup(group);user2.setGroup(group);這兩句加上后,運(yùn)行的結(jié)果如下

42、,可以看到t_user表的groupId字段為1,參考了t_group的主鍵。這個(gè)執(zhí)行的過程是這樣的,先將group對(duì)象插入t_group表為1,g1,由于級(jí)聯(lián)(Group->User)會(huì)將user和user2兩個(gè)對(duì)象插入t_user表,當(dāng)插user對(duì)象時(shí)候,user中的group字段不是一個(gè)null(是之前的group對(duì)象),所以又會(huì)發(fā)生級(jí)聯(lián),方向?yàn)椋║ser->Group),此時(shí)又會(huì)將這個(gè)group對(duì)象插入到t_group表,將插入后的主鍵id的值設(shè)為t_user中插入user對(duì)象時(shí)的groupId的值,但是會(huì)發(fā)現(xiàn)這個(gè)group對(duì)象剛才已經(jīng)插入過了,所以只是簡(jiǎn)單的將剛才插入gr

43、oup對(duì)象時(shí)的產(chǎn)生的主鍵id的值1給剛才的groupId值,最終將user插入到t_user中的記錄為2,u1,1,上面的級(jí)聯(lián)到重復(fù)插入那個(gè)group的時(shí)候就停止了,不會(huì)無窮的遞歸的進(jìn)行下去。插入user2對(duì)象時(shí),過程一樣。可以從這個(gè)過程得到兩個(gè)結(jié)論:(1)在同一個(gè)session中,同一個(gè)對(duì)象不會(huì)在數(shù)據(jù)庫中插入兩條不同的記錄。(2)級(jí)聯(lián)停止的條件為,對(duì)象里的關(guān)聯(lián)字段為null或在一個(gè)表插隊(duì)的對(duì)象已經(jīng)被插入過。t_user表t_group表若把testSaveGroup()改為如下:java view plain copy1. Test   &#

44、160;                                                 &#

45、160;                2. public void testSaveGroup()                          

46、0;                    3.     / 先new兩個(gè)user,一個(gè)group,然后把user加到group中                  &#

47、160;               4.     User user = new User();                      

48、0;                         5.     user.setName("u1");               &#

49、160;                                    6.              

50、;                                                  

51、;            7.     User user2 = new User();                          

52、                     8.     user2.setName("u2");                   

53、60;                               9.     Group group = new Group();      &#

54、160;                                      10.     group.setName("g1"); 

55、0;                                                 11.

56、    group.getUsers().add(user);                                         

57、60;  12.     group.getUsers().add(user2);                                      &

58、#160;    13.                                             

59、60;                              14.     / 新new一個(gè)group2,把它加到user2對(duì)象里面,下面save(group)會(huì)發(fā)生什么呢?      

60、;               15.     Group group2 = new Group();                      &#

61、160;                     16.     group2.setName("g2");                  

62、60;                               17.     user2.setGroup(group2);          

63、                                      18.            &#

64、160;                                                 &#

65、160;             19.     Session session = sessionFactory.getCurrentSession();                  20.  

66、0;  session.beginTransaction();                                           &

67、#160;21.     session.save(group);                                         &

68、#160;         22.     session.getTransaction().commit();                              

69、;       23.                                           &

70、#160;                               再new一個(gè)group2,然后set到user2的group屬性,這時(shí)測(cè)試會(huì)怎么樣?可以設(shè)想一下,結(jié)果應(yīng)該是這樣的,由于save(group),所以先插入t_group表,在t_group中插入一條記錄為1,g1,因?yàn)?/p>

71、t_group中有一個(gè)集合,里面有兩個(gè)user且都是非null的,所以會(huì)發(fā)生級(jí)聯(lián)(方向?yàn)镚roup->User),會(huì)插入這兩個(gè)user,這時(shí)候到底先插入哪一個(gè)user是不一定的,因?yàn)間roup中是個(gè)集合,假設(shè)按照add的順序先插user,后插user2,那么在t_user表中會(huì)先插入一條記錄2,u1,?,此時(shí)插入這條記錄的時(shí)候由于user中的group為null,所以不會(huì)發(fā)生級(jí)聯(lián),所以這里記錄的groupId為null,所以完整的是2,u1,null。接著插入user2對(duì)象,插入的記錄為3,u2,?,這里的?暫時(shí)不定,user2中的group為非null(設(shè)了group2對(duì)象,注意這個(gè)g

72、roup2之前沒有被插入過),所以會(huì)發(fā)生級(jí)聯(lián)插入t_group表,所以在t_group表中會(huì)插入4,g2,這條記錄是由插入3,u2,?級(jí)聯(lián)過來的(方向?yàn)閁ser->Group),所以上面的?會(huì)參考這條記錄的主鍵4,接著在t_group中插入4,g2的時(shí)候,因?yàn)檫@個(gè)group對(duì)象的集合set為null,所以不會(huì)發(fā)生級(jí)聯(lián),此時(shí)級(jí)聯(lián)就收斂了。最終t_group和t_user表的情況應(yīng)該是這樣。t_user表2,u1,null3,u2,4t_group表1,g14,g2測(cè)試的結(jié)果如下,和預(yù)期是一樣的。t_user表:t_group表:以上分析的是一對(duì)多的雙向關(guān)聯(lián),采用這種分析的思路看能不能解釋多

73、對(duì)多的雙向關(guān)聯(lián)的結(jié)果,做如下實(shí)驗(yàn),有兩個(gè)類Teacher和Student類,他們時(shí)間是多對(duì)多的關(guān)系。多對(duì)多的關(guān)系會(huì)映射成三張表,一張中間表,這里產(chǎn)生的三張表為teacher(id,name),student(id,name),t_s(teacher_id,student_id),teacher_id和student_id作為t_s的聯(lián)合主鍵,其中teacher_id參考了teacher表中的主鍵id,student_id參考了student表的主鍵id字段。其中關(guān)系的主導(dǎo)方向?yàn)門eacher->Student,此時(shí)中間表t_s可以看成teacher表中的一部分,只不過如果真的作為teac

74、her表的一部分,teacher表中會(huì)多出很多冗余的字段,所以把它獨(dú)立出來,只是我們可以參考一對(duì)多雙向關(guān)聯(lián)的情況下那樣看它。所以只有級(jí)聯(lián)的方向?yàn)閠eacher->student方向才會(huì)插入t_s表。Teacher類:java view plain copy1. package com.chen.hibernate.ormapping;  2.   3. import java.util.HashSet;  4. import java.util.Set;  5

75、.   6. import javax.persistence.CascadeType;  7. import javax.persistence.Entity;  8. import javax.persistence.GeneratedValue;  9. import javax.persistence.Id;  10. import javax.persistence.JoinColumn;  11. import&#

76、160;javax.persistence.JoinTable;  12. import javax.persistence.ManyToMany;  13.   14. Entity  15. public class Teacher   16.     private int id;  17.     private Str

77、ing name;  18.     private Set<Student> students = new HashSet<Student>();  19.   20.     Id  21.     GeneratedValue  22.     pu

78、blic int getId()   23.         return id;  24.       25.   26.     public void setId(int id)   27.      &

79、#160;  this.id = id;  28.       29.   30.     public String getName()   31.         return name;  32.     

80、0; 33.   34.     public void setName(String name)   35.          = name;  36.       37.   38.     ManyToMa

81、ny(cascade = CascadeType.ALL)  39.     JoinTable(name = "t_s", joinColumns = JoinColumn(name = "teacher_id", referencedColumnName = "id"), inverseJoinColumns = JoinC

82、olumn(name = "student_id", referencedColumnName = "id")  40.     public Set<Student> getStudents()   41.         return students;  42. 

83、0;     43.   44.     public void setStudents(Set<Student> students)   45.         this.students = students;  46.       

84、47.   Student類:java view plain copy1. package com.chen.hibernate.ormapping;  2.   3. import java.util.HashSet;  4. import java.util.Set;  5.   6. import javax.persistence.CascadeType;  7. import 

85、javax.persistence.Entity;  8. import javax.persistence.GeneratedValue;  9. import javax.persistence.Id;  10. import javax.persistence.ManyToMany;  11.   12. Entity  13. public class Student   14. 

86、0;   private int id;  15.     private String name;  16.     private Set<Teacher> teachers = new HashSet<Teacher>();  17.   18.    

87、60;Id  19.     GeneratedValue  20.     public int getId()   21.         return id;  22.       23.   24.   

88、0; public void setId(int id)   25.         this.id = id;  26.       27.   28.     public String getName()   29.  &#

89、160;      return name;  30.       31.   32.     public void setName(String name)   33.          = name;

90、60; 34.       35.   36.     / 設(shè)置Student類為被主導(dǎo)的類  37.     ManyToMany(mappedBy = "students", cascade = CascadeType.ALL)  38.     public

91、60;Set<Teacher> getTeachers()   39.         return teachers;  40.       41.   42.     public void setTeachers(Set<Teacher> teachers) 

92、  43.         this.teachers = teachers;  44.       45.   junit測(cè)試類java view plain copy1. package com.chen.hibernate.ormapping;  2.   3. import org.hibe

93、rnate.Session;  4. import org.hibernate.SessionFactory;  5. import org.hibernate.cfg.AnnotationConfiguration;  6. import org.hibernate.tool.hbm2ddl.SchemaExport;  7. import org.junit.AfterClass;  8. import org.junit.BeforeCla

94、ss;  9. import org.junit.Test;  10.   11. public class testMany2ManyCRUD   12.     private static SessionFactory sessionFactory = null;  13.   14.     Befo

95、reClass  15.     public static void beforeClass()   16.         new SchemaExport(new AnnotationConfiguration().configure().create(  17.        &#

96、160;        false, true);  18.         sessionFactory = new AnnotationConfiguration().configure()  19.              

97、;   .buildSessionFactory();  20.       21.   22.     Test  23.     public void testSaveStudent()   24.         /先new兩個(gè)st

98、udent和兩個(gè)teacher,然后把兩個(gè)student分別加到兩個(gè)teacher里  25.         Student student = new Student();  26.         student.setName("s1");  27.      

99、   Student student2 = new Student();  28.         student2.setName("s2");  29.   30.         Teacher teacher = new Teacher();

100、  31.         teacher.setName("t1");  32.         Teacher teacher2 = new Teacher();  33.         teacher2.setName("

101、t2");  34.         student.getTeachers().add(teacher);  35.         student.getTeachers().add(teacher2);  36.   37.         student2.ge

102、tTeachers().add(teacher);  38.         student2.getTeachers().add(teacher2);  39.   40.         /把這兩個(gè)teacher分別加到兩個(gè)student里,這是必須的,不然中間表t_s中不會(huì)有記錄  41.      &

103、#160;  for (Teacher t : student.getTeachers()   42.             t.getStudents().add(student);  43.             t.getStudents(

104、).add(student2);  44.           45.   46.         for (Teacher t : student2.getTeachers()   47.           

105、;  t.getStudents().add(student);  48.             t.getStudents().add(student2);  49.           50.   51.        &#

106、160;Session session = sessionFactory.getCurrentSession();  52.         session.beginTransaction();  53.         session.save(student);  54.       

107、;  session.save(student2);  55.         session.getTransaction().commit();  56.       57.   58.     Test  59.     public void test

108、SaveTeacher()   60.         /new兩個(gè)teacher和student,在save(teacher)時(shí),只需把兩個(gè)student分別加到兩個(gè)teacher中就可以了。  61.         /中間表t_s中也有數(shù)據(jù)  62.         Teacher teacher = new Teacher();  63.         teacher.setName("t1");  64.         Teacher teacher2 = new Teach

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論