版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、一、關系映射(重點)這里的關系是指:對象之間的關系,并不是指數據庫的關系。存在以下關系:1、多對一單向雙向2、一對多單向雙向3、一對一單向(主鍵、外鍵)雙向(主鍵、外鍵)4、多對多單向雙向1. many2one (單 向)場景:用戶和組;從用戶角度來,多個用戶屬于一個組(多對一),用戶3組(單向)使用hibernate開發(fā)的思路:先建立對象模型(領域模型),把實體抽取出來。目前兩個實體:用戶和組兩個實體,多個用戶屬于一個組,那么一個用戶都會對應于一個組,所以用戶實體中應 該有一個持有組的引用。(一)對象模型圖:(二)關系模型:t userid I name I groupid張三 201008
2、李四201008t_groupid |name*1201008(三)關聯(lián)映射的本質:將關聯(lián)關系映射到數據庫,所謂的關聯(lián)關系是對象模型在內存中一個或多個引用。實體類User實體類:public class User private int id; private String name; private Group group;public Group getGroup() return group; public void setGroup(Group group) this.group = group;public int getId() return id; public void set
3、Id(int id) this.id = id;public String getName() return name;public void setName(String name) = name;Group實體類:public class Group private int id; private String name; public int getId() return id; public void setId(int id) this.id = id;public String getName() return name; public void setName(String na
4、me) = name; 實體類建立完后,開始創(chuàng)建映射文件,先建立簡單的映射文件:xml方式:映射文件:、Group實體類的映射文件: generator class=native/ 2User實體類的映射文件: !-關聯(lián)映射 多對一的關系name:是維護的屬性(User.group),這樣表示在多的一端表里加入一個字段名稱為 group,但group與SQL中的關鍵字重復,所以需要重新命名字段(column=groupid)這樣這個字 段(groupid)會作為外鍵參照數據庫中group表(t_group也叫一的一端),也就是就在多的一 端加入一個外鍵指向一的一端。-3、淤 標簽:例如:關聯(lián)映
5、射多對一的關系name:是維護的屬性(User.group),這樣表示在多的一端表里加入一個字段名稱為group,但group與 SQL中的關鍵字重復,所以需要重新命名字段(column=groupid).這樣這個字段(groupid)會作為外鍵參 照數據庫中group表 (t_group也叫一的一端),也就是就在多的一端加入一個外鍵指向一的一端。多對一存儲(先存儲group,對象持久化狀態(tài)后再保存user),即先存儲一的一方,再存儲多的一方session = sessionFactory.openSession();tx = session.beginTransaction();Group
6、group = new Group();group.setName(201008);session.save(group); /存儲 Group 對象。User user1 = new User();user1.setName(張三);user1.setGroup(group);/設置用戶所屬的組User user2 = new User();user2.setName(李四);user2.setGroup(group);/設置用戶所屬的組/開始存儲session.save(user1);/ 存儲用戶session.save(user2);mit();/提交事務執(zhí)行后hibernate執(zhí)行以下
7、SQL語句:Hibernate: insert into t_group (name) values (?)Hibernate: insert into t_user (name, groupid) values (?, ?)Hibernate: insert into t user (name, groupid) values (?, ?)注意:如果上面的session.save(group)不執(zhí)行,則存儲不存儲不成功。則拋出 TransientObjectException 異 常。因為Group為Transient狀,Object的id沒有分配值。結果:persistent狀態(tài)的對象是不
8、能引用Transient狀態(tài)的對象以上代碼操作,必須首先保存group對象,再保存user對象。我們可以利用cascade(級聯(lián))方式,不需 要先保存group對象。而是直接保存user對象,這樣就可以在存儲user之前先把group存儲了。利用cascade屬性是解決TransientObjectException異常的一種手段。(七)重要屬性-cascade (級聯(lián)):級聯(lián)的意思是指定兩個對象之間的操作聯(lián)運關系,對一個對象執(zhí)行了操作之后,對其指定的級聯(lián)對象也需 要執(zhí)行相同的操作,取值:all、none、save_update、delete1、all:代碼在所有的情況下都執(zhí)行級聯(lián)操作2、no
9、ne:在所有情況下都不執(zhí)行級聯(lián)操作(默認)3、save-update:在保存和更新的時候執(zhí)行級聯(lián)操作4、delete:在刪除的時候執(zhí)行級聯(lián)操作。1、xml例如:many-to-one name=group column=groupid cascade= saveupdate /多對一加載數據代碼如下:session =sessionFactory.openSession();tx = session.beginTransaction();User user = (User)session.load(User.class, 3);System.out.println(= + user.getNa
10、me();System.out.println(= + user.getGroup().getName();/提交事務mit();執(zhí)行后向SQL發(fā)出以下語句:Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_, user0_.groupid as groupid0_0_ from t_user user0_ where user0_.id=?Hibernate: select group0_.id as id1_0_, group0_.name as name1_0_ from t_group group0_ where
11、 group0_.id=?可以加載Group信息:因為采用了many-to-one這個標簽,這個標簽會在多的一端(User)加一個外鍵,指 向一的一端(Group),也就是它維護了從多到一的這種關系,多指向一的關系。當你加載多一端的數據時,它就 能把一的這一端數據加載上來。當加載User對象后hibernate會根據User對象中的groupid再來加載 Group信息給User對象中的group屬性。one2many 單向)在對象模型中,一對多的關聯(lián)關系,使用集合來表示。實例場景:班級對學生;Classes(班級)和Student(學生)之間是(一對多),班級學生(單向)(一)對象模型:(二
12、)關系模型:t_classest_studentid 1 nameclassesidid 1 name001accp 7二T張三001T李四001一對多關聯(lián)映射利用了多對一關聯(lián)映射原理。 多對一關聯(lián)映射:在多的一端加入一個外鍵指向一的一端,一對多關聯(lián)映射:也是在多的一端加入一個外鍵指向 一的一端,兩者使用的策略是一樣的,只是各自所站的角度不同。實體類Classes實體類: public class Classes private int id; private String name; /一對多通常使用Set來映射,Set是不可重復內容。 private Set students = new
13、HashSet(); public int getId() return id; public void setId(int id) this.id = id; public String getName() return name; public void setName(String name) = name;JStudent實體類: public class Student private int id; private String name; public int getId() return id; public void setId(int id) this.id = id; p
14、ublic String getName() return name; public void setName(String name) = name;Jxml方式:映射1、Student映射文件: generator class= native/ 2、Classes映射文件: generator class= native/! -標簽 映射一對多(映射set集合),name=”屬性集合名稱,然后在用key標 簽,在多的一端加入一個外鍵(column屬性指定列名稱)指向一的一端,再采用標簽 說明一對多,還指定標簽中name=students這個集合中的類型要使用完整的類路徑(例如: class
15、=com.accp.hibernate.Student) -導出至數據庫(hbm ddl)生成的SQL語句:create table t_classes (id integer not null auto_increment, name varchar(255), primary key (id)create table t_student (id integer not null auto_increment, name varchar(255), classesid integer, primary key (id)alter table t_student add index FK4B9
16、0757070CFE27A (classesid), add constraint FK4B90757070CFE27A foreign key (classesid) references t_classes (id)一對多單向存儲實例,即先保存多的 方,再保存 的 方:session = sessionFactory.openSession();tx = session.beginTransaction();Student studentl = new Student();student1.setName( 10);session.save(studentl); /必需先存儲,否則在保存c
17、lassess時出錯.Student student2 = new Student();student2.setName(張三);session.save(student2); /必需先存儲,否則在保存classess時出錯.Set students = new HashSet();students.add(studentl);students.add(student2);Classes classes = new Classes();classes.setName( accp);classes.setStudents(students);session.save(classes);mit()
18、;(七)生成的SQL語句:Hibernate:insertintot_student(name)values(?)Hibernate:insertintot_student(name)values(?)Hibernate:insertintotclasses(name)values(?)Hibernate: update t_student set classesid=? where id=?Hibernate: update t_student set classesid=? where id=?一對多,在一的一端維護關系的缺點:因為是在一的一端維護關系,這樣會發(fā)出多余的更新語句,這樣在批量
19、數據時,效率不高。還有一個,當在多的一端的那個外鍵設置為非空時,則在添加多的一端數據時會發(fā)生錯誤,數據存儲不成功。一對多單向數據加載:session = sessionFactory.openSession();tx = session.beginTransaction();Classes classes = (Classes)session.load(Classes.class, 2);System.out.println(= + classes.getName();Set students = classes.getStudents();for (Iterator iter = stude
20、nts.iterator();iter.hasNext();)Student student = iter.next();System.out.println(student.getName();mit();(十)加載生成SQL語句:Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?Hibernate: select students0_.classesid as classesid1_, students0_.id
21、as id1_, students0_.id as id1_0_, students0_.name as name1_0_ from t_student students0_ where students0_.classesid=?one2many (雙向)是加載學生時,能夠把班級加載上來。當然加載班級也可以把學生加載上來(學生 班級)xml方式:映射學生映射文件修改后的:generator class= native/如果在一對多的映射關系中采用一的一端來維護關系的話會存在以下兩個缺點:如果多的一端那個外鍵設置為 非空時,則多的一端就存不進數據;會發(fā)出多于的Update語句,這樣會影響效率。
22、所以常用對于一對多的映 射關系我們在多的一端維護關系,并讓一的一端維護關系失效(見下面屬性)。代碼:!-fe簽映射一對多(映射set集合),name=屬性集合名稱然后在用fe簽,在多的一端加入一個外鍵(column屬性指定列名稱)指向一的一端再采用標簽說明一對多,還指定標簽中name=students這個集合中的類型要使用完整的類路徑(例如:class=com.accp.hibernate.Student)inverse=true:從一的一端維護關系失效(反轉),(默認false)這樣如果在一的一端維護關系則不會發(fā)出U pdate語句。-數據保存:一對多數據保存,從多的一端進行保存:sessi
23、on = sessionFactory.getSession();tx = session.beginTransaction();Classes classes = new Classes();classes.setName(accp);session.save(classes);Student student1 = new Student();student1.setName(張三);student1.setClasses(classes);session.save(student1);Student student2 = new Student();student2.setName(李四)
24、;student2.setClasses(classes);session.save(student2);/提交事務mit();關于 inverse屬性:inverse主要用在一對多和多對多雙向關聯(lián)上,inverse可以被設置到集合標簽上,默認inverse 為false,所以我們可以從一的一端和多的一端維護關聯(lián)關系,如果設置inverse為true,則我們只能從多的一端維護關聯(lián)關系。注意:雙向關聯(lián)中雙方都設置inverse= fals e的話,必會導致雙方都重復更新同一個關系。但是如果雙方都設 立inverse= true的話,雙方都不維護關系的更新,這也是不行的,好在一對多中的一端:man
25、y-to-one默認 是inverse= false,避免了這種錯誤的產生。(四)Inverse 和 cascade 區(qū)別:Inverse是關聯(lián)關系的控制方向Casecade操作上的連鎖反應(五)一對多雙向關聯(lián)映射總結:在一的一端的集合上使用key,在對方表中加入一個外鍵指向一的一端在多的一端采用 many-to-one注意:keyfe簽指定的外鍵字段必須和many-to-one指定的外鍵字段一致,否則引用字段的錯誤如果在一的一端維護一對多的關系,hibernate會發(fā)出多余的update語句,所以我們一般在多的一端來維護關 系。4. one2one關聯(lián)映射兩個對象之間是一對一的關系,如Per
26、son-IdCard(人身份證號)有兩種策略可以實現一對一的關聯(lián)映射 主鍵關聯(lián):即讓兩個對象具有相同的主鍵值,以表明它們之間的一一對應的關系;數據庫表不會有額外 的字段來維護它們之間的關系,僅通過表的主鍵來關聯(lián)。 唯一外鍵關聯(lián)(重要):外鍵關聯(lián),本來是用于多對一的配置,但是如果加上唯一的限制之后,也可以用 來表示一對一關聯(lián)關系。IdCardid intcardNo varchar(18)對象模型Persionid in!name varchar(20)(一)唯一外鍵關聯(lián)-單向1、說明:人一- 身份證號(PersonIdCard),從IdCard看不至I Person對象2、對象模型需要在Per
27、son類中持有IdCard的一個引用idCard,【J IdCard中沒有Person的引用Personf-一IdCard金id : int &name : String 鈕dCad : IdCard翎d : int ,cadNo : String1 ;3、關系模型關系模型目的:是實體類映射到關系模型(數據庫中),是要求persion中添加一個外鍵指向idcardt personidInamelidcard (唯一)I 張三 I 001I李四| 002t idcardid|cardNo卜 001 002|3625311986080302584、實體類:/
28、*人一實體類*/public class Person private int id;private String name;private IdCard idCard; /弓I用IdCard對象public int getId() return id; public void setId(int id) this.id = id;public String getName() return name;public void setName(String name) = name;public IdCard getIdCard() return idCard;public void setId
29、Card(IdCard idCard) this.idCard = idCard; 5、xml映射IdCard實體類的映射文件:因為IdCard是被引用的,所以沒有什么特殊的映射generator class=native/Person實體類的映射文件在映射時需要添加一個外鍵的映射,就是指定IdCard的引用的映射。這樣映射到數據庫時,就會自動添加 一個字段并作用外鍵指向被引用的表!- :在多的一端(當前Person端),加入一個外鍵(當前為idCard)指向一的 一端(當前IdCard),但多對一關聯(lián)映射字段是可以重復的,所以需要加入一個唯一條件unique=true,這樣就可以此字段唯一了
30、。-6、存儲測試Session session = sf.getCurrentSession();IdCard idCard = new IdCard();idCard.setCardNo(3625311985080302 65);session.beginTransaction();/如果先不保存idCard,則出拋出Transient異常,因為idCard不是持久化狀態(tài)。session.save(idCard);Person person = new Person();person.setName(張三);person.setIdCard(idCard);session.save(pers
31、on);session.getTransaction().commit();(二)唯一外鍵關聯(lián)-雙向1、說明:人 身份證號(PersonIdCard)雙向:互相持有對方的引用2、對象模型:Person7 zIdCard%id : int &name : String idCard : IdCard曼id : int cardNo : String person : Person3、關系模型:關系模型沒有任務變化,同單向4、實體類:實體類,只是相互持有對象的引用,并且要求getter和setter方法5、xml映射Person實體類映射文件:同單向的沒有變化IdCard實體類映射文件:如果使用同
32、樣的方法映射,這樣就會在表中也添加一個外鍵指向對象,但對象已 經有一個外鍵指向自己了,這樣就造成了庸字段,因為不需要在表另外添加字段,而是讓hibernate在加載 這個對象時,會根據對象的ID到對方的表中查詢外鍵等于這個ID的記錄,這樣就把對象加載上來了。也同 樣需要使用one-to-one標簽來映射,但是需要使用property-ref屬性來指定對象持有你自己的引用的成員屬 性名稱(是gettxxxx后面的名稱),這樣在生成數據庫表時,就不會再添加一個多于的字段了。數據加載時 hibernate會根據這些配置自己加載數據!-fe簽:告訴hibernate如何加載其關聯(lián)對象 property
33、-refM性:是根據哪個字段進行比較加載數據- (三)主鍵關聯(lián)-單向(不重要)主鍵關聯(lián):即讓兩個對象具有相同的主鍵值,以表明它們之間的一一對應的關系;數據庫表不會有額外的字 段來維護它們之間的關系,僅通過表的主鍵來關聯(lián)。1、說明:人。 身份證號(Person IdCard),從IdCard看不至I Person對象2、對象模型站在人的角度來看,對象模型與唯一外鍵關聯(lián)一個,只是關系模型不同3、關系模型因為是person引用idcard,所以idcard要求先有值。而person的主鍵值不是自己生成的。而是參考idcard4、實體類:實體類同一對一唯一外鍵關聯(lián)的實體類一個,在person對象中持有
34、idcard對象的引用(代碼見唯一外鍵關系)5、xml映射IdCard映射文件,先生成IDgenerator class= native/Person實體類映射文件,ID是根據IdCard主鍵值!-因為主鍵不是自己生成的,而是作為一個外鍵(來源于其它值),所以使用foreign生成策略 foreign :使用另外一個相關聯(lián)的對象的標識符,通常和聯(lián)合起來使用。再使用元素 的屬性值指定相關聯(lián)對象(這里Person相關聯(lián)的對象為idCard,則標識符為idCard的id) 為了能夠在加載person數據同時加載IdCard數據,所以需要使用一個標簽來設置這 個功能。-!- 元素屬性name的值是固定
35、為property - idCard!- 標簽表示如何加載它的引用對象(這里引用對象就指idCard這里的name值是idCard),同時也 說是一對一的關系。默認方式是根據主鍵加載(把person中的主鍵取出再到IdCard中來取相關 IdCard數據。)我們也說過此主鍵也作為一個外鍵引用7IdCard,所以需要加一個數據庫限制(外 鍵約束)constrained=true-6、存,測試session = HibernateUtils.getSession();tx = session.beginTransaction();IdCard idCard = new IdCard();idCar
36、d.setCardNo;Person person = new Person();person.setName(張三);person.setIdCard(idCard);/不會出現 TransientObjectException 異常/因為一對一主鍵關鍵映射中,默認了 cascade屬性。session.save(person);mit();7、總結讓兩個實體對象的ID保持相同,這樣可以避免多余的字段被創(chuàng)建idCard(四)主鍵關聯(lián)-雙向(不重要)主鍵關聯(lián):即讓兩個對象具有相同的主鍵值,以表明它們之間的一一對應的關系;數據庫表不會有額外的字 段來維護它
37、們之間的關系,僅通過表的主鍵來關聯(lián)。主鍵關聯(lián)映射,實際是數據庫的存儲結構并沒有變化,只是要求雙方都可以持有對象引用,也就是說實體模型變化,實體類都相互持有對方引用。另外映射文件也變化了。1、xml映射Person實體類映射文件不變,IdCard 如下:5.多對多關聯(lián)映射 單向(many-to-many)一般的設計中,多對多關聯(lián)映射,需要一個中間表 Hibernate會自動生成中間表Hibernate使用many-to-many標簽來表示多對多的關聯(lián)多對多的關聯(lián)映射,在實體類中,跟一對多一樣,也是用集合來表示的。實例場景:用戶與他的角色(一個用戶擁有多個角色,一個角色還可以屬于多個用戶)對象模型
38、:關系模型:t_usert_user_role(第三方表,表示 user 和 role 關系)t_roleid 1 nameid 1 nameid I name1張三1李四1王五1111129IoI區(qū)域經理I業(yè)務主管I項目經理2|2I3I13I23I3Role實體類:public class Role private int id;private String name;public int getId() return id;public void setId(int id) this.id = id;public String getName() ;public void setName(
39、String name) ,=name,User實體類:public class User private int id;private String name;private Set roles; /Role對象的集合 public int getId() return id;public void setId(int id) this.id = id;public String getName() Role映射文件:generator class= native/User映射文件:!-使用標簽映射集合(set),標簽中的name值為對象屬性名(集合roles),而使用table 屬性是用于
40、生成第三方表名稱,例:table=t_user_role,但是第三方面中的字段是自動加入的,作為外鍵 分別指向其它表。所以表標簽設置,例:,意思是:在第三方表(t_user_role)中加入一個 外鍵并且指向當前的映射實體類所對應的表(t_user).使用來指定此映射集合所對象的類 (實例類),并且使用column屬性加入一個外鍵指向Role實體類所對應的表(t_role)-導出至數據庫表所生成SQL語句create table t_role (id integer not null auto_increment, name varchar(255), primary key (id)crea
41、te table t_user (id integer not null auto_increment, name varchar(255), primary key (id)create table t_user_role (userid integer not null, roleid integer not null, primary key (userid, roleid)alter table t_user_role add index FK331DEE5F1FB4B2D4 (roleid), add constraintFK331DEE5F1FB4B2D4 foreign key
42、(roleid) references t_role (id)alter table t_user_role add index FK331DEE5F250A083E (userid), add constraintFK331DEE5F250A083E foreign key (userid) references t_user (id)注:根據DDL語句可以看出第三方表的主鍵是一個復合主鍵(primary key (userid, roleid),也就是說 記錄不可以有相同的數據。多對多關聯(lián)映射單向數據存儲:session = HibernateUtils.getSession ();tx
43、= session.beginTransaction();Role r1 = new Role();r1.setName(區(qū)域經理);session.save(r1);Role r2 = new Role();r2.setName(業(yè)務主管);session.save(r2);Role r3 = new Role();r3.setName(項目經理);session.save(r3);User u1 = new User();u1.setName(張三);Set u1Roles = new HashSet();u1Roles.add(r1);u1Roles.add(r2);u1.setRole
44、s(u1Roles);User u2 = new User();u2.setName(李四);Set u2Roles = new HashSet();u2Roles.add(r2);u2Roles.add(r3);u2.setRoles(u2Roles);User u3 = new User();u3.setName(王五);Set u3Roles = new HashSet();u3Roles.add(r1);u3Roles.add(r2);u3Roles.add(r3);u3.setRoles(u3Roles);session.save(u1);session.save(u2);sessi
45、on.save(u3);mit();發(fā)出SQL語句:Hibernate:insertintot_role(name) values(?)Hibernate:insertintot_role(name) values(?)Hibernate:insertintot_role(name) values(?)Hibernate:insertintot_user(name) values(?)Hibernate:insertintot_user(name) values(?)Hibernate:insertintot_user(name) values(?)Hibernate:insertintot_
46、user_role (userid,roleid) values (?, ?)Hibernate:insertintot_user_role (userid,roleid) values (?, ?)Hibernate:insertintot_user_role (userid,roleid) values (?, ?)Hibernate:insertintot_user_role (userid,roleid) values (?, ?)Hibernate:insertintot_user_role (userid,roleid) values (?, ?)Hibernate:insertintot_user_role (userid,roleid) values (?, ?)Hibernate:insertintotuserrole (userid,roleid) values (?, ?)注:前三條SQL語句,添加Role記錄,第三條到第六條添加User,最后7條SQL語句是在向第三方表 (t_user_role)中添加多對多關系(User與Role關系)多對多關聯(lián)映射單向數據加載:se
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 樓宇自控弱電系統(tǒng)施工協(xié)議
- 商業(yè)綜合體建設招標合同范例
- 電子競技中心建設合同
- 商業(yè)招商居間合同范例
- 資金拆借合同三篇
- 車險賠付協(xié)議書(2篇)
- 工商注銷代理服務合同注意項
- 集體發(fā)包合同
- 績效管理合同范例
- 公司營銷人員合同范例
- 國內外建筑節(jié)能現狀及發(fā)展
- CNAS授權簽字人考核資料講課文檔
- 新能源電動汽車參考文獻有哪些
- 煤礦全員安全教育培訓考試試卷+答案
- 國土資源調查與管理
- 液壓氣動技術專題報告2000字
- GB 19517-2023國家電氣設備安全技術規(guī)范
- 促進學習的課堂評價
- DB14∕T 1722-2018 橋梁加固用碳纖維復合材料板材的耐久性應用技術要求
- 2023-2024學年遼寧省大連市小學語文五年級期末評估試卷附參考答案和詳細解析
- 河北2023年河北承德銀行招聘考試參考題庫含答案詳解
評論
0/150
提交評論