hibernate.hbm.xml详解
在Hibernate中,各表的映射文件….hbm.xml可以通過工具生成,例如在使用MyEclipse開發(fā)時,它提供了自動生成映射文件的工具。配置文件的基本結(jié)構(gòu)如下:
Xml代碼
1?<?xml?version="1.0"?encoding='UTF-8'?>???
2???
3?<!DOCTYPE?hibernate-mapping?PUBLIC???
4??????"-//Hibernate/Hibernate?Mapping?DTD?3.0//EN"???
5??????"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">???
6?<hibernate-mapping?package="包名">???
7????<class?name="類名"?table="表名">???
8???????<id?name="主鍵在java類中的字段名"?column="對應(yīng)表中字段"?type="類型?">???
9???????????<generator?class="主鍵生成策略"/>???
10???????</id>???
11???
12???????????……???
13?????</class>???
14?</hibernate-mapping>???
1.?主鍵(id)
Hibernate的主鍵生成策略有如下幾種:
1)?assigned
主鍵由外部程序負責(zé)生成,在?save()?之前指定。
2)?hilo
通過hi/lo?算法實現(xiàn)的主鍵生成機制,需要額外的數(shù)據(jù)庫表或字段提供高位值來源。
3)?seqhilo
與hilo?類似,通過hi/lo?算法實現(xiàn)的主鍵生成機制,需要數(shù)據(jù)庫中的?Sequence,適用于支持?Sequence?的數(shù)據(jù)庫,如Oracle。
4)?increment
主鍵按數(shù)值順序遞增。此方式的實現(xiàn)機制為在當(dāng)前應(yīng)用實例中維持一個變量,以保存著當(dāng)前的最大值,之后每次需要生成主鍵的時候?qū)⒋酥导?span style="font-family:'Times New Roman';">1作為主鍵。這種方式可能產(chǎn)生的問題是:不能在集群下使用。
5)?identity
采用數(shù)據(jù)庫提供的主鍵生成機制。如DB2、SQL?Server、MySQL?中的主鍵生成機制。
6)?sequence
采用數(shù)據(jù)庫提供的?sequence?機制生成主鍵。如?Oralce?中的Sequence。
7)?native
由?Hibernate?根據(jù)使用的數(shù)據(jù)庫自行判斷采用?identity、hilo、sequence?其中一種作為主鍵生成方式。
8)?uuid.hex
由?Hibernate?基于128?位?UUID?算法?生成16?進制數(shù)值(編碼后以長度32?的字符串表示)作為主鍵。
9)?uuid.string
與uuid.hex?類似,只是生成的主鍵未進行編碼(長度16),不能應(yīng)用在?PostgreSQL?數(shù)據(jù)中。
10)?foreign
使用另外一個相關(guān)聯(lián)的對象的標識符作為主鍵。
主鍵配置舉例如下:
Xml代碼
15?<id?name="id"?column="id"?type="java.lang.Integer">???
16??????????????<generator?class="native"/>???
17?</id>???
另外還可以擴展Hibernate的類來做自己的主鍵生成策略,具體例子見:http://www.javaeye.com/topic/93391。
2.?普通屬性(property)
???????開發(fā)人員可以打開網(wǎng)址:http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd
來查看hibernate3.0的dtd信息,可看到property的定義如下:
Xml代碼
18?<!ELEMENT?property?(meta*,(column|formula)*,type?)>???
19?<!ATTLIST?property?name?CDATA?#REQUIRED>???
20?<!ATTLIST?property?node?CDATA?#IMPLIED>???
21?<!ATTLIST?property?access?CDATA?#IMPLIED>???
22?<!ATTLIST?property?type?CDATA?#IMPLIED>???
23?<!ATTLIST?property?column?CDATA?#IMPLIED>???
24?<!ATTLIST?property?length?CDATA?#IMPLIED>???
25?<!ATTLIST?property?precision?CDATA?#IMPLIED>???
26?<!ATTLIST?property?scale?CDATA?#IMPLIED>???
27?<!ATTLIST?property?not-null?(true|false)?#IMPLIED>???
28?<!ATTLIST?property?unique?(true|false)?"false">???
29?<!ATTLIST?property?unique-key?CDATA?#IMPLIED>???
30?<!ATTLISTpropertyindexCDATA#IMPLIED>??????
31?<!--?include?the?columns?spanned?by?this?property?in?an?index?-->???
32?<!ATTLIST?property?update?(true|false)?#IMPLIED>???
33?<!ATTLIST?property?insert?(true|false)?#IMPLIED>???
34?<!ATTLIST?property?optimistic-lock?(true|false)?"true">???????????
35?<!--?only?supported?for?properties?of?a?class?(not?component)?-->???
36?<!ATTLIST?property?formula?CDATA?#IMPLIED>???
37?<!ATTLIST?property?lazy?(true|false)?"false">???
38?<!ATTLIST?property?generated?(never|insert|always)?"never">???
它的各屬性中比較常用的有:name(對應(yīng)的java類的屬性名稱)、column(對應(yīng)的表中的字段)、type(屬性的類型,eg.java.lang.String)、not-null(設(shè)置該屬性是否為空,為true時表示非空,默認為false)和length(字段的長度限制)。?示例如下:
Xml代碼
39?<property?name="accessname"?column="accessName"?type="java.lang.String"?not-null="true"?/>???
40?<property?name="state"?column="state"?type="java.lang.Byte"?not-null="true"?/>???
41?<property?name="description"?column="description"?type="java.lang.String"?/>??
3.?一對多關(guān)系(<many-to-one…/>和<set…></set>)
???????一對多關(guān)系一般是用在一個表與另一個表存在外鍵關(guān)聯(lián)的時候,例如用戶表的組織id與組織表存在外鍵關(guān)聯(lián),則“一”方為組織表,“多”方為用戶表,因為一個組織可以包含多個用戶,而一個用戶只能隸屬于一個組織。
????對于存在一對多關(guān)系和多對一關(guān)系的雙方,需要在…h(huán)bm.xml中進行相應(yīng)配置,這時在“一”方(例如:組織)需要在映射文件中添加<set…></set>元素,因為它包含多個“多”方的對象,一般的格式如下:
Xml代碼
42?<set?name="java映射類中對應(yīng)的屬性"?inverse="true"?lazy="true">???
43???<key?column="表中對應(yīng)字段"/>???
44??????<one-to-many?class="多方的類"/>???
45?</set>???
46???
47?<!--?示例?-->??
48?<set?name="userSet"?inverse="true"?lazy="true">???
49???????<key?column="orgId"/>???
50???????<one-to-many?class="User"/>???
51?</set>???
“多”方(例如:用戶)隸屬于一個“一”方對象,一般的格式如下:
Xml代碼
52?<many-to-one?name="java映射類中對應(yīng)的屬性"?column="表中對應(yīng)字段"?class="類名"?not-null="true"?/>???
53???
54?<!--?示例?-->??
55?<many-to-one?name="org"?column="orgId"?class="Organization"?not-null="true"?/>???
4.?一對一關(guān)系(<one-to-one…/>)
一對一關(guān)系相對一對多關(guān)系來說比較少見,但也在某些情況下要用到,例如有一個用戶的基本信息表(USER)和一個用戶的密碼表(PASSWD)就存在一對一的關(guān)系。下面來看一下一對一關(guān)系在Hibernate的配置。
Xml代碼
56?<!--?其中主表(eg.?用戶的基本信息表)的配置?-->??
57???
58?<one-to-one?name="主表對象中子表對象的屬性名"?class="子表對象的類名"?cascade="save-update"/>???
59???
60?<one-to-one?name="password"?class="com.amigo.dao.pojo.Passwd"?cascade="save-update"/>???
61???
62?<!--?子表(eg.?用戶的密碼表)的配置?-->??
63???
64?<one-to-one?name="子表對象中主表對象的屬性名"?class="主表對象的類名"?constrained="true"?/>???
65???
66?<one-to-one?name="user"?class="com.amigo.dao.pojo.User?"?constrained="true"?/>???
5.?多對多關(guān)系(<many-to-many…/>)
在數(shù)據(jù)庫設(shè)計時,一般將多對多關(guān)系轉(zhuǎn)換為兩個一對多(或多對一)關(guān)系,例如在基于角色的權(quán)限系統(tǒng)中,用戶和角色存在的關(guān)系就是典型的多對多關(guān)系,即一個用戶可以具有多個角色,而一個角色又可以為多個用戶所有,一般在設(shè)計時,都會加一個用戶與角色的關(guān)聯(lián)表,該表與用戶表以及角色表都存在外鍵關(guān)聯(lián)。
在本小節(jié)中講述的是沒有分解的多對多關(guān)系在Hibernate中如何配置。設(shè)置格式如下:
Xml代碼
67?<set?name="java對象的屬性名"?table="表名"?cascade="all"?outer-join="false">?????
68?????<key?column="表的對應(yīng)字段"/>?????
69?????<many-to-many?class="另一個表的對象類"?column="另一個表的字段"/>?????
70?</set>?????
71???
72?<!--?t_user方?-->??
73?<set?name="roleSet"?table="t_user"?cascade="all"?outer-join="false">?????
74?????<key?column="roleId"/>?????
75?????<many-to-many?class="com.amigo.dao.pojo.Role"?column="roleId"/>?????
76?</set>?????
77???
78?<!--?t_role方?-->??
79?<set?name="userSet"?table="t_role"?cascade="all"?outer-join="false">?????
80?????<key?column="roleId"/>?????
81?????<many-to-many?class="com.amigo.dao.pojo.User"?column="roleId"/>?????
82?</set>
6.?完整實例
在本小節(jié)中舉一些.hbm.xml映射文件的例子,讓開發(fā)人員對其有一個感性的認識。接下來講述一個用戶表(tbl_user)、用戶與角色關(guān)聯(lián)表(tbl_user_role)、角色表(tbl_role)以及組織表(tbl_organization)的例子。
(1)tbl_user
Xml代碼
1?<?xml?version="1.0"?encoding='UTF-8'?>???
2???
3?<!DOCTYPE?hibernate-mapping?PUBLIC???
4???????????"-//Hibernate/Hibernate?Mapping?DTD?3.0//EN"???
5????????"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">???
6???
7?<hibernate-mapping?package="com.amigo.dao.pojo">???
8?????<class?name="User"?table="tbl_user">???
9???????<id?name="loginname"?column="loginName"?type="java.lang.String">???
10???????????<generator?class="assigned"/>???
11??????</id>???
12??????<property?name="name"?column="name"?type="java.lang.String"?not-null="true"?/>???
13??????<property?name="password"?column="password"?type="java.lang.String"?not-null="true"?/>???
14??????<property?name="mobile"?column="mobile"?type="java.lang.String"?/>???
15??????<property?name="telephone"?column="telephone"?type="java.lang.String"?/>???
16??????<property?name="email"?column="email"?type="java.lang.String"?/>???
17??????<property?name="createtime"?column="createTime"?type="java.util.Date"?not-null="true"?/>???
18??????<property?name="lastlogintime"?column="lastLoginTime"?type="java.util.Date"?/>???
19?????<property?name="logintimes"?column="loginTimes"?type="java.lang.Long"?not-null="true"?/>???
20??????<property?name="state"?column="state"?type="java.lang.Byte"?not-null="true"?/>???
21?????<property?name="description"?column="description"?type="java.lang.String"?/>???
22?????<many-to-one?name="organization"?column="orgId"?class="Organization"?not-null="true"?/>???
23?????<set?name="userRoleSet"?inverse="true"?cascade="all-delete-orphan"?lazy="true">???
24?????????<key?column="loginName"/>???
25?????????<one-to-many?class="UserRole"/>???
26?????</set>???
27?</hibernate-mapping>???
(2)tbl_organization
Xml代碼
28?<?xml?version="1.0"?encoding='UTF-8'?>???
29???
30?<!DOCTYPE?hibernate-mapping?PUBLIC???
31??????????????"-//Hibernate/Hibernate?Mapping?DTD?3.0//EN"???
32??????????????????"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">???
33???
34?<hibernate-mapping?package="com.amigo.dao.pojo">???
35????<class?name="Organization"?table="tbl_organization">???
36?????????<id?name="orgid"?column="orgId"?type="java.lang.Long">???
37????????????<generator?class="native"/>???
38?????????</id>???
39???
40?????????<property?name="parentorgid"?column="parentOrgId"?type="java.lang.Long"?not-null="true"?/>???
41?????????<property?name="orgname"?column="orgName"?type="java.lang.String"?not-null="true"?/>???
42?????????<property?name="orgfullname"?column="orgFullName"?type="java.lang.String"?/>???
43?????????<property?name="orglevel"?column="orgLevel"?type="java.lang.Integer"?not-null="true"?/>???
44?????????<property?name="state"?column="state"?type="java.lang.Byte"?not-null="true"?/>???
45?????????<property?name="description"?column="description"?type="java.lang.String"?/>???
46?????????<property?name="creator"?column="creator"?type="java.lang.String"?/>???
47?????????<property?name="createtime"?column="createTime"?type="java.util.Date"?/>???
48?????????<set?name="userSet"?inverse="true"?lazy="true">???
49?????????????<key?column="orgId"/>???
50?????????????<one-to-many?class="User"/>???
51?????????</set>???
52?????</class>???
53?</hibernate-mapping>???
(3)tbl_user_role
1?1、到底在哪用cascade="..."????
2????cascade屬性并不是多對多關(guān)系一定要用的,有了它只是讓我們在插入或刪除對像時更方便一些,只要在cascade的源頭上插入或是刪除,所有?cascade的關(guān)系就會被自己動的插入或是刪除。便是為了能正確的cascade,unsaved-value是個很重要的屬性。Hibernate通?過這個屬性來判斷一個對象應(yīng)該save還是update,如果這個對象的id是unsaved-value的話,那說明這個對象不是?persistence????object要save(insert);如果id是非unsaved-value的話,那說明這個對象是persistence????object(數(shù)據(jù)庫中已存在),只要update就行了。saveOrUpdate方法用的也是這個機制。?????
3???????
4????2、到底在哪用inverse="ture"??????
5?????“set的inverse屬性決定是否把對set的改動反映到數(shù)據(jù)庫中去。inverse=false————反映;inverse=true————不反映”inverse屬性默認為false??
6???????
7????inverse屬性默認是false的,就是說關(guān)系的兩端都來維護關(guān)系。這個意思就是說,如有一個Student,????Teacher和TeacherStudent表,Student和Teacher是多對多對多關(guān)系,這個關(guān)系由TeacherStudent這個表來表?現(xiàn)。那么什么時候插入或刪除TeacherStudent表中的記錄來維護關(guān)系呢?在用hibernate時,我們不會顯示的對?TeacherStudent表做操作。對TeacherStudent的操作是hibernate幫我們做的。hibernate就是看hbm文件中指?定的是"誰"維護關(guān)系,那個在插入或刪除"誰"時,就會處發(fā)對關(guān)系表的操作。前提是"誰"這個對象已經(jīng)知道這個關(guān)系了,就是說關(guān)系另一頭的對象已經(jīng)set?或是add到"誰"這個對象里來了。前面說過inverse默認是false,就是關(guān)系的兩端都維護關(guān)系,對其中任一個操作都會處發(fā)對表系表的操作。當(dāng)在?關(guān)系的一頭,如Student中的bag或set中用了inverse="true"時,那就代表關(guān)系是由另一關(guān)維護的(Teacher)。就是說當(dāng)這插?入Student時,不會操作TeacherStudent表,即使Student已經(jīng)知道了關(guān)系。只有當(dāng)Teacher插入或刪除時才會處發(fā)對關(guān)系表的?操作。所以,當(dāng)關(guān)系的兩頭都用inverse="true"是不對的,就會導(dǎo)致任何操作都不處發(fā)對關(guān)系表的操作。當(dāng)兩端都是inverse="false"或是default值是,在代碼對關(guān)系顯示的維護也是不對的,會導(dǎo)致在關(guān)系表中插入兩次關(guān)系。?????
8???????
9????在一對多關(guān)系中inverse就更有意義了。在多對多中,在哪端inverse="true"效果差不多(在效率上)。但是在一對多中,如果要一方維護關(guān)?系,就會使在插入或是刪除"一"方時去update"多"方的每一個與這個"一"的對象有關(guān)系的對象。而如果讓"多"方面維護關(guān)系時就不會有update?操作,因為關(guān)系就是在多方的對象中的,直指插入或是刪除多方對象就行了。當(dāng)然這時也要遍歷"多"方的每一個對象顯示的操作修關(guān)系的變化體現(xiàn)到DB中。不管?怎樣說,還是讓"多"方維護關(guān)系更直觀一些。???
10???
11??????(1)對one-to-many而言,改變set,會讓hibernate執(zhí)行一系列的update語句,?不會delete/insert數(shù)據(jù)???
12??????(2)對many-to-many而言,改變set,只修改關(guān)系表的數(shù)據(jù),不會影響many-to-many的另一方。???
13??????(3)雖然one-to-many和many-to-many的數(shù)據(jù)庫操作不一樣,但目的都是一個:維護數(shù)據(jù)的一致性。?????
14???????
15????3、cascade和inverse有什么區(qū)別??????
16????可以這樣理解,cascade定義的是關(guān)系兩端對象到對象的級聯(lián)關(guān)系;而inverse定義的是關(guān)系和對象的級聯(lián)關(guān)系。???
17????inverse只對set+one-to-many(或many-to-many)有效,對many-to-one,?one-to-one無效。cascade對關(guān)系標記都有效。???
18???
19????inverse對集合對象整體起作用,cascade對集合對象中的一個一個元素起作用,如果集合為空,那么cascade不會引發(fā)關(guān)聯(lián)操作。???
20????比如將集合對象置為null,?school.setStudentSet(null)???
21?????inverse導(dǎo)致hibernate執(zhí)行:udpate?STUDENT?set?SCHOOL_ID=null?where?SCHOOL_ID=????
22?????cascade則不會執(zhí)行對STUDENT表的關(guān)聯(lián)更新,?因為集合中沒有元素。???
23????再比新增一個school,?session.save(school)???
24?????inverse導(dǎo)致hibernate執(zhí)行:???
25?????for(?對(school的每一個student?){???
26???????udpate?STUDENT?set?SCHOOL_ID=??where?STUDENT_ID=?//將學(xué)生的school_id改為新的school的id??
27??????}???
28?????cascade導(dǎo)致hibernate執(zhí)行:???
29?????for(?對school的每一個student?){???
30???????session.save(aStudent);//對學(xué)生執(zhí)行save操作??
31??????}???
32???extends:如果改變集合中的部分元素(比如新增一個元素),???
33?????inverse:?hibernate先判斷哪些元素改變了,對改變的元素執(zhí)行相應(yīng)的sql???
34?????cascade:?它總是對集合中的每個元素執(zhí)行關(guān)聯(lián)操作。???
35??????(在關(guān)聯(lián)操作中,hibernate會判斷操作的對象是否改變)???
36????兩個起作用的時機不同:???
37?????cascade:在對主控方操作時,級聯(lián)發(fā)生。???
38?????inverse:?在flush時(commit會自動執(zhí)行flush),對session中的所有set,hibernate判斷每個set是否有變化,???
39?????對有變化的set執(zhí)行相應(yīng)的sql,執(zhí)行之前,會有個判斷:if(?inverse?==true?)return;可以看出cascade在先,inverse在后。???
40?????inverse?對set?+?one-to-many?和?set?+?many-to-many?起的作用不同。hibernate生成的sql不同。???
41????????對one-to-many,hibernate對many方的數(shù)據(jù)庫表執(zhí)行update語句。???
42????????對many-to-many,?hibernate對關(guān)系表執(zhí)行insert/update/delte語句,注意不是對many方的數(shù)據(jù)庫表而是關(guān)系表。???
43??????cascase?對set都是一致的,不管one-to-many還是many-to-many。都簡單地把操作傳遞到set中的每個元素。所以它總是更新many方的數(shù)據(jù)庫表。???
44???
45???4、cascade和inverse有什么相同????
46????這兩個屬性本身互不影響,但起的作用有些類似,都能引發(fā)對關(guān)系表的更新。???
47???
48???5、?建議:只對set?+?many-to-many設(shè)置inverse=false,其他的標記不考慮inverse屬性,都設(shè)為inverse=true。對cascade,一?般對many-to-one,many-to-many,constrained=true的one-to-one?不設(shè)置級聯(lián)刪除。?
轉(zhuǎn)載于:https://www.cnblogs.com/heavyhe/archive/2011/09/05/4547352.html
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的hibernate.hbm.xml详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php里Array2xml
- 下一篇: delphi DLL动态链接库