1.OID和主鍵生成策略
1.1.主鍵(Primary key):
在數(shù)據(jù)庫(kù)表中能夠唯一識(shí)別每一行記錄的一個(gè)字段或者多個(gè)字段的組合.
主鍵特點(diǎn):
非空且唯一,簡(jiǎn)單.一般的使用一個(gè)列來(lái)表示主鍵.
主鍵分類:
名稱 | 區(qū)別 |
---|---|
自然主鍵 | 主鍵具有業(yè)務(wù)含義,比如身份證號(hào)碼,必須要收到輸入. |
代理主鍵 | 主鍵沒(méi)有業(yè)務(wù)含義,僅僅起唯一標(biāo)識(shí),一般由數(shù)據(jù)庫(kù)服務(wù)器自動(dòng)生成. |
單字段主鍵 | 在一張表中使用某一列作為主鍵. |
復(fù)合主鍵 | 在一張表中使用多列一起,聯(lián)合作為主鍵. |
1.2.OID
1.在hibernate中,一個(gè)對(duì)象必須要有一個(gè)id,這個(gè)id對(duì)應(yīng)數(shù)據(jù)庫(kù)的主鍵;
2.在hibernate當(dāng)中,把對(duì)象中對(duì)應(yīng)數(shù)據(jù)表主鍵的屬性,對(duì)象標(biāo)識(shí)符(OID).
3.OID可以是單個(gè)屬性,也可以使多個(gè)屬性(復(fù)合主鍵的映射)
-
4.OID的重要作用:
1.OID在Hibernate中唯一標(biāo)識(shí)了一個(gè)對(duì)象(在數(shù)據(jù)庫(kù)表中主鍵唯一的表示了一行數(shù)據(jù));
2.在一級(jí)緩存中,Type+ID唯一標(biāo)識(shí)了一級(jí)緩存中相同的數(shù)據(jù) .
3.一般情況,在domain當(dāng)中,需要用OID屬性來(lái)重寫equals和hashcode法方法 5.單個(gè)OID都使用<id>元素來(lái)映射,name代表OID屬性的名稱,column表示對(duì)應(yīng)表中主鍵的列名.
6.id元素都有一個(gè)generator子元素,規(guī)定了主鍵的生成策略.
自然主鍵:assigned,在保存之前必須手動(dòng)設(shè)置值,assigned只針對(duì)于自然主鍵
保存改對(duì)象的時(shí)候,必須手動(dòng)輸入該值.
1.3.代理主鍵的生成方式(讓數(shù)據(jù)庫(kù)生成或讓hibernate生成):
- 1:uuid:使用uuid作為主鍵值 ,使用uuid這一種生成策略,此時(shí)主鍵必須是String類型.
- 2:increment:增長(zhǎng)方式.
1,hibernate生成主鍵
2,先查詢當(dāng)前表id最大值,自增1后作為當(dāng)前對(duì)象的id
3,主鍵類型可以遞增;不能在集群(多個(gè)hibernate應(yīng)用使用同一個(gè)數(shù)據(jù)庫(kù))的情況下使用; - 3:identity:
1,使用數(shù)據(jù)庫(kù)本身的id生成策略:MySQL:auto_increment;
2,數(shù)據(jù)庫(kù)本身必須支持id自動(dòng)增長(zhǎng)策略,Oracle不能使用. - 4:sequence:序列
1,使用序列生成id,如果只配置sequence,會(huì)創(chuàng)建一個(gè)默認(rèn)的序列hibernate_sequence;
2,數(shù)據(jù)庫(kù)本身必須支持序列
//可以通過(guò)sequence參數(shù)來(lái)指定表對(duì)應(yīng)的序列生成器的名字
<generator class="sequence">
<param name="sequence">IDDOMAIN_SEQ</param>
</generator>
- 5:native:
1,使用數(shù)據(jù)庫(kù)本地的主鍵生成策略
對(duì)于mysql:auto_increment;
對(duì)于oracle:使用默認(rèn)的sequence; - 6:org.hibernate.id.enhanced.TableGenerator
1,相當(dāng)于序列生成器,hibernate使用一張hibernate_seqences這樣的表來(lái)模擬序列生成器
2,如果只配置org.hibernate.id.enhanced.TableGenerator,相當(dāng)于所有的表都使用default這一個(gè)序列生成器
3,會(huì)造成很多額外的SQL
<generator class="org.hibernate.id.enhanced.TableGenerator">
<param name="segment_value">IDDOMAIN_SEQ</param>
</generator>
1.4.選擇:
1,自然主鍵還是代理主鍵;
2,使用數(shù)據(jù)庫(kù)來(lái)生成主鍵還是使用hibernate來(lái)生成主鍵(應(yīng)用是否需要移植數(shù)據(jù)庫(kù))
是否在集群環(huán)境中使用
3,性能問(wèn)題
4,一般來(lái)說(shuō),使用native就可以了.
2.Session中的方法
常用方法(已學(xué)):
Transaction beginTransaction():開(kāi)啟一個(gè)事務(wù)
Transaction getTransaction():獲取一個(gè)事務(wù)
Serializable save(Object o):保存一個(gè)對(duì)象
void update(Object o):修改一個(gè)對(duì)象
void delete(Object o):刪除一個(gè)對(duì)象
Object get(Class type,Serializable id):根據(jù)主鍵查詢指定類型的對(duì)象
Query createQuery(String hql):根據(jù)hql創(chuàng)建一個(gè)查詢對(duì)象
void close():關(guān)閉Session
void clear():清除一級(jí)緩存所有對(duì)象
void evict(Object o):清除一級(jí)緩存中制定的對(duì)象
按照方法的功能,把session的方法分為:
2.1.事務(wù)相關(guān):
Transactionsession.beginTransaction():標(biāo)記打開(kāi)當(dāng)前session綁定的事務(wù)對(duì)象墨礁。
Transactionsession.getTransaction():得到和當(dāng)前session綁定的事務(wù)對(duì)象。
2.2.一級(jí)緩存相關(guān):
session.clear():清除一級(jí)緩存中所有的對(duì)象。
boolean contains(Object entity):判斷一級(jí)緩存中是否有給定的對(duì)象。
session.evict(Object entity):從一級(jí)緩存中清除指定的對(duì)象搁痛。
session.flush():把一級(jí)緩存中的臟數(shù)據(jù)同步到數(shù)據(jù)庫(kù)中渠概。
session.refresh(Objectentity):強(qiáng)制重新查詢對(duì)象,相當(dāng)于把數(shù)據(jù)庫(kù)中的數(shù)據(jù)同步到一級(jí)緩存中择示。
2.3.持久化操作相關(guān):
session.delete(Objectentity):從數(shù)據(jù)庫(kù)中刪除一個(gè)對(duì)象
session.update(Objectentity):更新一個(gè)對(duì)象
session.get(ClassentityType,Serializableid):根據(jù)主鍵查詢一個(gè)對(duì)象
session.load(ClassentityType,Serializableid):根據(jù)主鍵加載一個(gè)對(duì)象
1.load方法是一個(gè)延遲加載(lazy-load)的方法;把對(duì)象的獲壬孤谩(SQL)延遲到了真正使用這個(gè)對(duì)象的時(shí)候才發(fā)送对妄;
2.真正使用?當(dāng)使用一個(gè)非主鍵屬性的時(shí)候敢朱;
3.load實(shí)現(xiàn)原理剪菱?使用動(dòng)態(tài)代理,為load的domain動(dòng)態(tài)創(chuàng)建了一個(gè)子類拴签,在這個(gè)子類中孝常,復(fù)寫所有非主鍵調(diào)用方法,在這些方法中蚓哩,去發(fā)送.
session.save(Objectentity):保存一個(gè)對(duì)象
1.同步JPA的接口方法构灸;
2.和save的區(qū)別:在沒(méi)有事務(wù)環(huán)境下,save方法會(huì)發(fā)送INSERT SQL岸梨,persist不會(huì)喜颁;)
session.saveOrUpdate(Objectentity):如果對(duì)象沒(méi)有保存到數(shù)據(jù)庫(kù),則保存曹阔,如果已經(jīng)保存過(guò)半开,則更新。
session.merge(Objectentity):等同于saveOrUpdate方法赃份。
1.同步JPA的接口方法寂拆;
2.和saveOrUpdate的區(qū)別:在沒(méi)有事務(wù)環(huán)境下奢米,saveOrUpdate方法會(huì)發(fā)送INSERT SQL,merge不會(huì)纠永;
2.4.其他:
session.close():關(guān)閉session鬓长,相當(dāng)于關(guān)閉了和session關(guān)聯(lián)的connection對(duì)象。關(guān)閉session之后尝江,就不能再使用這個(gè)session完成持久化相關(guān)的操作涉波。
session.doWork(Workwork):Hibernate提供給程序員直接使用JDBC的一個(gè)途徑。
session.doReturningWork(ReturningWork):Hibernate提供給程序員直接使用JDBC的一種途徑炭序。
Serializablesession.getIdentifier(Objectentity):得到一個(gè)對(duì)象的主鍵值
session 上面所有的方法都在促使對(duì)象的狀態(tài)發(fā)生改變.
2.5.Hibernate中對(duì)象保存的方法:
persist和方法save方法都表示保存一個(gè)對(duì)象,但是persist方法必須運(yùn)行在事務(wù)空間內(nèi).
save(e); //沒(méi)有事務(wù)環(huán)境,也會(huì)發(fā)送INSERT INTO語(yǔ)句
persist(e);//沒(méi)有事務(wù)環(huán)境,不會(huì)發(fā)送INSERT INTO語(yǔ)句.
Hibernate實(shí)現(xiàn)了JPA的規(guī)范,就得提供JPA中的方法,而在JPA中持久化操作的方法就叫做:persist.
建議使用persist方法.
2.6.保存或更新操作方法:
session.saveOrUpdate(Objectentity):如果對(duì)象沒(méi)有保存到數(shù)據(jù)庫(kù)怠蹂,則保存,如果已經(jīng)保存過(guò)少态,則更新。
- 如果對(duì)象存在OID,則update
- 如果對(duì)象不存在OID,則save.
merge方法相當(dāng)于saveOrUpdate方法.必須運(yùn)行在事務(wù)空間內(nèi),是JPA規(guī)范的方法.
2.7.加載或查詢指定類型和IOD的一個(gè)對(duì)象:
Object obj = session.load(Classs type,Serializable id)
Object obj = session.get(Classs type,Serializable id)
- get方法返回的總是持久化狀態(tài)的對(duì)象;get方法立刻發(fā)送一條SELECT語(yǔ)句,結(jié)果可以用if-null來(lái)判斷.
- load方法并不會(huì)立刻發(fā)送一條SELECT語(yǔ)句去查詢對(duì)象,而要到真正在使用(使用一個(gè)非主鍵屬性)這個(gè)對(duì)象的時(shí)候,才會(huì)去發(fā)送SELECT語(yǔ)句,我們把這種方式叫做延遲加載(lazy-load/懶加載).
如果對(duì)象沒(méi)有被加載過(guò),則發(fā)送一條SELECT語(yǔ)句,去加載對(duì)象,再返回屬性值.
load方法返回的對(duì)象永遠(yuǎn)不可能為空,所以不能使用ifnull來(lái)判斷,如果load了一個(gè)不存在的id的對(duì)象,在使用的時(shí)候報(bào)錯(cuò);
load方法返回的對(duì)象是持久化對(duì)象;
load方法也會(huì)從一級(jí)緩存中獲取數(shù)據(jù)
load原理:
- 1).Hibernate框架的中的javassist組件創(chuàng)建了代理類以及對(duì)象.
- 2).該對(duì)象提供了非主鍵屬性的getter方法和toString方法.
- 3):該對(duì)象存在是否加載完畢的狀態(tài),訪問(wèn)屬性是先判斷對(duì)象是否加載完畢,如是直接返回該屬性之,否則發(fā)送SQL查詢?cè)搶?duì)象.
如果在session關(guān)閉之前沒(méi)有去實(shí)例化延遲加載對(duì)象,報(bào)錯(cuò):
LazyInitializationException: could not initialize proxy - no Session.
LoadEventListener$LoadType類
一般的,load方法是Hibernate內(nèi)部使用的,我們就使用get方法即可.
3.持久化對(duì)象的狀態(tài)
3.1.通過(guò)三個(gè)問(wèn)題,引出對(duì)象狀態(tài).
-
問(wèn)題1: 主鍵生成策略不同,save操作時(shí)發(fā)生INSERT語(yǔ)句的時(shí)機(jī)不同.
native: 在執(zhí)行save方法的時(shí)候發(fā)送INSERT SQL.
increment: 在提交事務(wù)的時(shí)候,才發(fā)送INSERT SQL. 問(wèn)題2: 刪除對(duì)象的時(shí)候,沒(méi)有立刻發(fā)生DELETE語(yǔ)句,而是在提交事務(wù)的時(shí)候發(fā)送的.
問(wèn)題3: 為什么在事務(wù)環(huán)境下,通過(guò)get方法得到的對(duì)象,只要修改了屬性值,會(huì)發(fā)生UPDATE語(yǔ)句.
結(jié)論:
通過(guò)上述三個(gè)測(cè)試,我們發(fā)現(xiàn)Session中的方法和SQL的執(zhí)行沒(méi)有任何關(guān)系.
問(wèn)題:那到底SQL的執(zhí)行和什么有關(guān)系呢?有什么關(guān)系呢? ---->和對(duì)象的狀態(tài)有關(guān)系.
3.2.持久化對(duì)象的狀態(tài)有哪一些,怎么劃分的?
劃分的規(guī)則:
1):當(dāng)前對(duì)象是否有OID(該對(duì)象在表中對(duì)應(yīng)有一個(gè)id值.)
2):對(duì)象是否被Session所管理(對(duì)象是否在一級(jí)緩存中).
狀態(tài) | - | 特點(diǎn) |
---|---|---|
臨時(shí)狀態(tài)/瞬時(shí)態(tài)(transient) | 剛剛用new語(yǔ)句創(chuàng)建易遣,沒(méi)有被持久化彼妻,不處于session中。 | 沒(méi)有oid,不在session當(dāng)中. |
持久化狀態(tài)(persistent) | 已經(jīng)被持久化豆茫,加入到session的緩存中侨歉。 | 有oid,在session當(dāng)中 |
脫管態(tài)/游離狀態(tài)(detached) | 已經(jīng)被持久化,但不處于session中揩魂。 | 有oid,不在session當(dāng)中 |
刪除狀態(tài)(removed) | 對(duì)象有關(guān)聯(lián)的ID幽邓,并且在Session管理下,但是已經(jīng)計(jì)劃被刪除火脉。 | 有oid,在session當(dāng)中,最終的效果是被刪除. |
判斷規(guī)則:
對(duì)象是否有OID牵舵,判斷對(duì)象是否與Session關(guān)聯(lián)(被Hibernate管理)
3.3.狀態(tài)的之間的轉(zhuǎn)換:
-
Transient(臨時(shí)狀態(tài)/瞬時(shí)狀態(tài)):
特點(diǎn),沒(méi)有OID,不被Session所管理.情況1):new語(yǔ)句剛創(chuàng)建了一個(gè)對(duì)象.
情況2):刪除狀態(tài)的對(duì)象,在事務(wù)提交之后,對(duì)象處于臨時(shí)狀態(tài).
臨時(shí)狀態(tài)是沒(méi)有ID的,測(cè)試可以打印該對(duì)象的ID,發(fā)現(xiàn)存在ID.
--->設(shè)置hibernate.cfg.xml的屬性:hibernate.use_identifier_rollback=true
-
Removed(刪除狀態(tài)):
特點(diǎn):此時(shí)有OID,被Session所管理中,但是最終會(huì)被刪除.情況1:delete方法讓持久化狀態(tài)和游離狀態(tài)變成刪除狀態(tài).
但是刪除狀態(tài)的對(duì)象必須等到session刷新(flush),事務(wù)提交時(shí)才真正從數(shù)據(jù)庫(kù)中刪除. -
Persistent(持久化狀態(tài)):
特點(diǎn):有OID,被Session所管理.情況1):save方法把臨時(shí)狀態(tài)轉(zhuǎn)換為持久化狀態(tài).
情況2):save方法把游離對(duì)象變成另一個(gè)持久化狀態(tài).
保存一個(gè)對(duì)象之后,提交事務(wù)/關(guān)閉Session,此時(shí)對(duì)象處于游離狀態(tài),再創(chuàng)建新的Session來(lái)保存該對(duì)象.
情況3):get和load方法返回的是持久化對(duì)象.
情況4):Query.list方法返回的是持久化對(duì)象,在處理大數(shù)據(jù)量的時(shí)候,需要及時(shí)清理一級(jí)緩存(分頁(yè)查詢).
情況5):update方法把游離對(duì)象變成持久化對(duì)象. -
Detached(游離狀態(tài)/托管狀態(tài)):
特點(diǎn):有OID,但是不被Session所管理(不在一級(jí)緩存中).情況1):session.close()方法把所有的持久化對(duì)象變成游離對(duì)象.
情況2):session.clear()方法把所有持久化對(duì)象變成游離對(duì)象.
情況3):session.evivt(Object)方法把制定的持久化對(duì)象變成游離對(duì)象.
情況4):使用new創(chuàng)建對(duì)象,并設(shè)置OID(數(shù)據(jù)庫(kù)存在該ID);
3.4.總結(jié):
Session中的方法僅僅只是改變對(duì)象的狀態(tài),不負(fù)責(zé)發(fā)送SQL/默認(rèn)情況下事務(wù)提交的時(shí)候發(fā)送SQL.
- 問(wèn)題1: 主鍵生成策略不同,save操作時(shí)發(fā)生INSERT語(yǔ)句的時(shí)機(jī)不同.
native: 在執(zhí)行save方法的時(shí)候發(fā)送INSERT SQL.
increment: 在提交事務(wù)的時(shí)候,才發(fā)送INSERT SQL.
原因是:save方法僅僅是把臨時(shí)狀態(tài)的對(duì)象轉(zhuǎn)換為持久化狀態(tài),本身不負(fù)責(zé)發(fā)送SQL.
臨時(shí)狀態(tài)的對(duì)象沒(méi)有IOD,調(diào)用save方法之后,變成持久化狀態(tài),就必須有OID.
此時(shí):從臨時(shí)狀態(tài)轉(zhuǎn)換為持久化狀態(tài),只需要獲取OID即可.
native:表示數(shù)據(jù)庫(kù)主鍵的自增長(zhǎng),只有發(fā)送SQL,才能獲取主鍵,----->OID.
increment:先發(fā)送SELECT語(yǔ)句查詢id,(擁有了OID),不需要發(fā)送INSERET來(lái)獲取ID. - 問(wèn)題2: 刪除對(duì)象的時(shí)候,沒(méi)有立刻發(fā)生DELETE語(yǔ)句,而是在提交事務(wù)的時(shí)候發(fā)送的.
原因是:delete方法僅僅是改變對(duì)象的狀態(tài),本身不負(fù)責(zé)發(fā)送SQL.
- 問(wèn)題3: 為什么在事務(wù)環(huán)境下,通過(guò)get方法得到的對(duì)象,只要修改了屬性值,會(huì)發(fā)生UPDATE語(yǔ)句.
原因是:通過(guò)get查詢操作得到的對(duì)象處于持久化狀態(tài)(有OID,存在于一級(jí)緩存中).
此時(shí),修改了非IOD的屬性值,發(fā)現(xiàn)一級(jí)緩存中的數(shù)據(jù)和快照區(qū)域的數(shù)據(jù)不同(臟數(shù)據(jù)),
Hibernate就會(huì)做比較(一級(jí)緩存和快照區(qū)),發(fā)送不同,就發(fā)送UPDATE語(yǔ)句,做數(shù)據(jù)同步.
session的flush方法,負(fù)責(zé)把一級(jí)緩存中的臟數(shù)據(jù)同步到數(shù)據(jù)庫(kù)中去.
User u = new User(); //臨時(shí)狀態(tài)
u.setName("XX");
session.save(u);---->SELECT max(id) //持久化狀態(tài)
//持久化狀態(tài)可以被刪除.
User u = session.get(User.class,1L);
session.delete(u);
User u = new User();
u.setId(1L);//游離狀態(tài)
-----------------------------------
4.集合映射
之前對(duì)象中的屬性:都是簡(jiǎn)單數(shù)據(jù)類型(一個(gè)類型對(duì)應(yīng)一個(gè)值.String,Integer,Date)
屬性是集合類型:
案例:根據(jù)一個(gè)用戶有一個(gè)郵箱地址,分析表結(jié)構(gòu)的設(shè)計(jì).
因?yàn)榇藭r(shí):一個(gè)用戶最多只有一個(gè)郵件地址,可以直接郵件作為用戶表的一列.
如何一個(gè)用戶有多個(gè)郵箱地址,分析表結(jié)構(gòu)的設(shè)計(jì).
存儲(chǔ)多個(gè)數(shù)據(jù),此時(shí)只能使用集合.
Set/List/Map.
Set:不記錄添加順序,元素不能重復(fù).
List:記錄添加的順序,元素運(yùn)行重復(fù).
Map:存儲(chǔ)鍵值對(duì),每次存儲(chǔ)都要存儲(chǔ)key和value.
在開(kāi)發(fā)中靈活選用,根據(jù)各自的特點(diǎn)和具體的需求.
Set set = new HashSet();
List list = new ArrayList();
Map map = new HashMap();
集合屬性只能以接口聲明(當(dāng)持久化某個(gè)實(shí)例時(shí), Hibernate 會(huì)自動(dòng)把程序中的集合實(shí)現(xiàn)類替換成 Hibernate 自己的集合實(shí)現(xiàn)類),
集合屬性只能以接口聲明(當(dāng)持久化某個(gè)實(shí)例時(shí), Hibernate 會(huì)自動(dòng)把程序中的集合實(shí)現(xiàn)類替換成 Hibernate 自己的集合實(shí)現(xiàn)類
---->PersistentSet
---->PersistentList
選擇:
如果集合類型使用Set,則使用<set>元素.
如果集合類型使用List,則使用<bag>元素.
Hibernate對(duì)集合賬號(hào)的原生支持兩種排序方式(了解):
- 1:內(nèi)存中排序,Hibernate把數(shù)據(jù)加載到內(nèi)存中的Java集合中,根據(jù)集合自身的功能來(lái)排序(自然排序/定制排序).
- 2:數(shù)據(jù)庫(kù)排序,Hibernate通過(guò)SELECT語(yǔ)句從數(shù)據(jù)庫(kù)查詢數(shù)據(jù)的時(shí)候,使用ORDER BY字句進(jìn)行排序.
排序?qū)傩?/th> | <set> | <bag> | <list> | <map> |
---|---|---|---|---|
sort屬性 | 支持 | 不支持 | 不支持 | 支持 |
order-by屬性 | 支持 | 支持 | 不支持 | 支持 |
需求:根據(jù)郵件的地址逆序排序.
<!-- 映射Collection/List集合 -->
<bag name="emailBag" table="user_emails_bag" order-by="address DESC">
<key column="user_id" />
<element column="address" type="string" />
</bag>
order-by="address DESC":
注意:address表示數(shù)據(jù)庫(kù)表的列名.
5.對(duì)象之間的關(guān)系(寫少量代碼):
5.1.依賴關(guān)系:
如果A對(duì)象離開(kāi)了B對(duì)象,A對(duì)象就不能正常編譯,則A對(duì)象依賴B對(duì)象.
在A類使用到了B(調(diào)用了B的方法,調(diào)用了B的字段).
//依賴關(guān)系:
class B1{}
class B2{}
class A{
B2 b2;//A依賴B2
void doWork(){
B1 b1 = new B1();//A依賴于B1
}
}
5.2.關(guān)聯(lián)關(guān)系:
A對(duì)象依賴B對(duì)象,并且把B對(duì)象作為A對(duì)象的一個(gè)字段,則A和B是關(guān)聯(lián)關(guān)系.
class B{}
class A{
B b;//關(guān)聯(lián)關(guān)系
}
class Deparment{
//一對(duì)多
List<Employee> employees = new ...;
}
class Employee{
}
Deparment d = new ...();
Employee e1 = new ....();
Employee e2 = new ....();
Employee e3 = new ....();
d.getEmployess().add(e1);
d.getEmployess().add(e2);
d.getEmployess().add(e3);
class Deparment{}
class Employee{
//多對(duì)一
Department dept;
}
Deparment d = new ...();
Employee e1 = new ....();
Employee e2 = new ....();
Employee e3 = new ....();
e1.setDept(d);
e2.setDept(d);
e2.setDept(d);
按照多重性分:
關(guān)聯(lián)關(guān)系 | 解釋 | 例子 |
---|---|---|
1).一對(duì)一 : | 一個(gè)A對(duì)象屬于一個(gè)B對(duì)象; 一個(gè)B對(duì)象屬于一個(gè)A對(duì)象. |
QQ號(hào)碼對(duì)應(yīng)一個(gè)QQ空間. |
2).一對(duì)多: | 一個(gè)A對(duì)象包含多個(gè)B對(duì)象. | 一個(gè)部門包含多個(gè)員工對(duì)象, 此時(shí)我們使用集合來(lái)封裝B對(duì)象. |
3).多對(duì)一: | 多個(gè)A對(duì)象同屬于一個(gè)B對(duì)象, 并且每個(gè)A對(duì)象只能屬于一個(gè)B對(duì)象. 設(shè)計(jì)表的時(shí)候:外鍵在many這一方 在開(kāi)發(fā)設(shè)計(jì)中:添加一個(gè)many方對(duì)象的時(shí)候, 往往通過(guò)下拉列表去選擇one方. |
多個(gè)員工對(duì)象屬于同一個(gè)部門. |
4).多對(duì)多 | 一個(gè)A對(duì)象屬于多個(gè)B對(duì)象,一個(gè)B對(duì)象屬于多個(gè)A對(duì)象. 通過(guò)中間表來(lái)表示關(guān)系. |
一個(gè)老師可以有多個(gè)學(xué)生, 一個(gè)學(xué)生可以有多個(gè)老師. |
按照導(dǎo)航性分:
如果通過(guò)A對(duì)象中的某一個(gè)屬性可以訪問(wèn)該屬性對(duì)應(yīng)的B對(duì)象,則說(shuō)A可以導(dǎo)航到B.
- | - |
---|---|
1).單向: | 只能從A通過(guò)屬性導(dǎo)航到B,B不能導(dǎo)航到A. |
2).雙向: | A可以通過(guò)屬性導(dǎo)航到B,B也可以通過(guò)屬性導(dǎo)航到A. |
判斷方法:
1,判斷都是從對(duì)象的實(shí)例上面來(lái)看的;
2,判斷關(guān)系必須確定一對(duì)屬性;
3,判斷關(guān)系必須確定具體需求;
5.3.聚合關(guān)系:
表示整體和部分的關(guān)系,整體和部分之間可以相互獨(dú)立存在,一定是有兩個(gè)模塊來(lái)分別管理整體和部分.
整體和部分可以分開(kāi).
5.4.組合關(guān)系:
強(qiáng)聚合關(guān)系,但是整體和部分不能獨(dú)立存在,一定是在一個(gè)模塊中同時(shí)管理整體和部分,生命周期必須相同.
單據(jù)和單據(jù)明顯/購(gòu)物車
5.5.泛化關(guān)系
:其實(shí)就是繼承關(guān)系.