<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    【永恒的瞬間】
    ?Give me hapy ?

     

     

    對(duì)象和關(guān)系數(shù)據(jù)庫(kù)之間的映射通常是用一個(gè)XML文檔(XML document)來(lái)定義的。這個(gè)映射文檔被設(shè)計(jì)為易讀的, 并且可以手工修改。映射語(yǔ)言是以Java為中心,這意味著映射文檔是按照持久化類的定義來(lái)創(chuàng)建的, 而非表的定義。

    請(qǐng)注意,雖然很多Hibernate用戶選擇手寫XML映射文檔,但也有一些工具可以用來(lái)生成映射文檔, 包括XDoclet,Middlegen和AndroMDA。

    讓我們從一個(gè)映射的例子開始:

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="eg">
    <class name="Cat"
    table="cats"
    discriminator-value="C">
    <id name="id">
    <generator class="native"/>
    </id>
    <discriminator column="subclass"
    type="character"/>
    <property name="weight"/>
    <property name="birthdate"
    type="date"
    not-null="true"
    update="false"/>
    <property name="color"
    type="eg.types.ColorUserType"
    not-null="true"
    update="false"/>
    <property name="sex"
    not-null="true"
    update="false"/>
    <property name="litterId"
    column="litterId"
    update="false"/>
    <many-to-one name="mother"
    column="mother_id"
    update="false"/>
    <set name="kittens"
    inverse="true"
    order-by="litter_id">
    <key column="mother_id"/>
    <one-to-many class="Cat"/>
    </set>
    <subclass name="DomesticCat"
    discriminator-value="D">
    <property name="name"
    type="string"/>
    </subclass>
    </class>
    <class name="Dog">
    <!-- mapping for Dog could go here -->
    </class>
    </hibernate-mapping>

    我們現(xiàn)在開始討論映射文檔的內(nèi)容。我們只描述Hibernate在運(yùn)行時(shí)用到的文檔元素和屬性。 映射文檔還包括一些額外的可選屬性和元素,它們?cè)谑褂胹chema導(dǎo)出工具的時(shí)候會(huì)影響導(dǎo)出的數(shù)據(jù)庫(kù)schema結(jié)果。 (比如, not-null 屬性。)

    6.1.1. Doctype

    所有的XML映射都需要定義如上所示的doctype。DTD可以從上述URL中獲取, 從hibernate-x.x.x/src/net/sf/hibernate目錄中、 或hibernate.jar文件中找到。Hibernate總是會(huì)首先在它的classptah中搜索DTD文件。 如果你發(fā)現(xiàn)它是通過連接Internet查找DTD文件,就對(duì)照你的classpath目錄檢查XML文件里的DTD聲明。

    6.1.2. hibernate-mapping

    這個(gè)元素包括一些可選的屬性。schemacatalog屬性, 指明了這個(gè)映射所連接(refer)的表所在的schema和/或catalog名稱。 假若指定了這個(gè)屬性,表名會(huì)加上所指定的schema和catalog的名字?jǐn)U展為全限定名。假若沒有指定,表名就不會(huì)使用全限定名。 default-cascade指定了未明確注明cascade屬性的Java屬性和 集合類Hibernate會(huì)采取什么樣的默認(rèn)級(jí)聯(lián)風(fēng)格。auto-import屬性默認(rèn)讓我們?cè)诓樵冋Z(yǔ)言中可以使用 非全限定名的類名。

    <hibernate-mapping
    schema="schemaName"                          (1)
    catalog="catalogName"                        (2)
    default-cascade="cascade_style"              (3)
    default-access="field|property|ClassName"    (4)
    default-lazy="true|false"                    (5)
    auto-import="true|false"                     (6)
    package="package.name"                       (7)
    />
    (1)

    schema (可選): 數(shù)據(jù)庫(kù)schema的名稱。

    (2)

    catalog (可選): 數(shù)據(jù)庫(kù)catalog的名稱。

    (3)

    default-cascade (可選 - 默認(rèn)為 none): 默認(rèn)的級(jí)聯(lián)風(fēng)格。

    (4)

    default-access (可選 - 默認(rèn)為 property): Hibernate用來(lái)訪問屬性的策略。可以通過實(shí)現(xiàn)PropertyAccessor接口 自定義。

    (5)

    default-lazy (可選 - 默認(rèn)為 true): 指定了未明確注明lazy屬性的Java屬性和集合類, Hibernate會(huì)采取什么樣的默認(rèn)加載風(fēng)格。

    (6)

    auto-import (可選 - 默認(rèn)為 true): 指定我們是否可以在查詢語(yǔ)言中使用非全限定的類名(僅限于本映射文件中的類)。

    (7)

    package (可選): 指定一個(gè)包前綴,如果在映射文檔中沒有指定全限定的類名, 就使用這個(gè)作為包名。

    假若你有兩個(gè)持久化類,它們的非全限定名是一樣的(就是兩個(gè)類的名字一樣,所在的包不一樣--譯者注), 你應(yīng)該設(shè)置auto-import="false"。假若說你把一個(gè)“import過”的名字同時(shí)對(duì)應(yīng)兩個(gè)類, Hibernate會(huì)拋出一個(gè)異常。

    注意hibernate-mapping 元素允許你嵌套多個(gè)如上所示的 <class>映射。但是最好的做法(也許一些工具需要的)是一個(gè) 持久化類(或一個(gè)類的繼承層次)對(duì)應(yīng)一個(gè)映射文件,并以持久化的超類名稱命名,例如: Cat.hbm.xmlDog.hbm.xml,或者如果使用繼承,Animal.hbm.xml

    6.1.3. class

    你可以使用class元素來(lái)定義一個(gè)持久化類:

    <class
    name="ClassName"                              (1)
    table="tableName"                             (2)
    discriminator-value="discriminator_value"     (3)
    mutable="true|false"                          (4)
    schema="owner"                                (5)
    catalog="catalog"                             (6)
    proxy="ProxyInterface"                        (7)
    dynamic-update="true|false"                   (8)
    dynamic-insert="true|false"                   (9)
    select-before-update="true|false"             (10)
    polymorphism="implicit|explicit"              (11)
    where="arbitrary sql where condition"         (12)
    persister="PersisterClass"                    (13)
    batch-size="N"                                (14)
    optimistic-lock="none|version|dirty|all"      (15)
    lazy="true|false"                             (16)
    entity-name="EntityName"                      (17)
    check="arbitrary sql check condition"         (18)
    rowid="rowid"                                 (19)
    subselect="SQL expression"                    (20)
    abstract="true|false"                         (21)
    entity-name="EntityName"                      (22)
    node="element-name"                           (23)
    />
    (1)

    name (可選): 持久化類(或者接口)的Java全限定名。 如果這個(gè)屬性不存在,Hibernate將假定這是一個(gè)非POJO的實(shí)體映射。

    (2)

    table (可選 - 默認(rèn)是類的非全限定名): 對(duì)應(yīng)的數(shù)據(jù)庫(kù)表名。

    (3)

    discriminator-value (可選 - 默認(rèn)和類名一樣): 一個(gè)用于區(qū)分不同的子類的值,在多態(tài)行為時(shí)使用。它可以接受的值包括 nullnot null

    (4)

    mutable (可選,默認(rèn)值為true): 表明該類的實(shí)例是可變的或者可變的。

    (5)

    schema (可選): 覆蓋在根<hibernate-mapping>元素中指定的schema名字。

    (6)

    catalog (可選): 覆蓋在根<hibernate-mapping>元素中指定的catalog名字。

    (7)

    proxy (可選): 指定一個(gè)接口,在延遲裝載時(shí)作為代理使用。 你可以在這里使用該類自己的名字。

    (8)

    dynamic-update (可選, 默認(rèn)為 false): 指定用于UPDATE 的SQL將會(huì)在運(yùn)行時(shí)動(dòng)態(tài)生成,并且只更新那些改變過的字段。

    (9)

    dynamic-insert (可選, 默認(rèn)為 false): 指定用于INSERT的 SQL 將會(huì)在運(yùn)行時(shí)動(dòng)態(tài)生成,并且只包含那些非空值字段。

    (10)

    select-before-update (可選, 默認(rèn)為 false): 指定Hibernate除非確定對(duì)象真正被修改了(如果該值為true-譯注),否則不會(huì)執(zhí)行SQL UPDATE操作。在特定場(chǎng)合(實(shí)際上,它只在一個(gè)瞬時(shí)對(duì)象(transient object)關(guān)聯(lián)到一個(gè) 新的session中時(shí)執(zhí)行的update()中生效),這說明Hibernate會(huì)在UPDATE 之前執(zhí)行一次額外的SQL SELECT操作,來(lái)決定是否應(yīng)該執(zhí)行 UPDATE

    (11)

    polymorphism(多態(tài)) (可選, 默認(rèn)值為 implicit (隱式) ): 界定是隱式還是顯式的使用多態(tài)查詢(這只在Hibernate的具體表繼承策略中用到-譯注)。

    (12)

    where (可選) 指定一個(gè)附加的SQLWHERE 條件, 在抓取這個(gè)類的對(duì)象時(shí)會(huì)一直增加這個(gè)條件。

    (13)

    persister (可選): 指定一個(gè)定制的ClassPersister

    (14)

    batch-size (可選,默認(rèn)是1) 指定一個(gè)用于 根據(jù)標(biāo)識(shí)符(identifier)抓取實(shí)例時(shí)使用的"batch size"(批次抓取數(shù)量)。

    (15)

    optimistic-lock(樂觀鎖定) (可選,默認(rèn)是version): 決定樂觀鎖定的策略。

    (16)

    lazy (optional): 通過設(shè)置lazy="false", 所有的延遲加載(Lazy fetching)功能將未被激活(disabled)。

    (17)

    entity-name (可選): Hibernate3允許一個(gè)類進(jìn)行多次映射( 默認(rèn)情況是映射到不同的表),并且允許使用Maps或XML代替Java層次的實(shí)體映射 (也就是實(shí)現(xiàn)動(dòng)態(tài)領(lǐng)域模型,不用寫持久化類-譯注)。 更多信息請(qǐng)看第 5.4 節(jié) “動(dòng)態(tài)模型(Dynamic models)” and 第 19 章 XML映射

    (18)

    check (可選): 這是一個(gè)SQL表達(dá)式, 用于為自動(dòng)生成的schema添加多行(multi-row)約束檢查

    (19)

    rowid (可選): Hibernate可以使用數(shù)據(jù)庫(kù)支持的所謂的ROWIDs,例如: Oracle數(shù)據(jù)庫(kù),如果你設(shè)置這個(gè)可選的rowid, Hibernate可以使用額外的字段rowid實(shí)現(xiàn)快速更新。ROWID是這個(gè)功能實(shí)現(xiàn)的重點(diǎn), 它代表了一個(gè)存儲(chǔ)元組(tuple)的物理位置。

    (20)

    subselect (可選): 它將一個(gè)不可變(immutable)并且只讀的實(shí)體映射到一個(gè)數(shù)據(jù)庫(kù)的 子查詢中。它用于實(shí)現(xiàn)一個(gè)視圖代替一張基本表,但是最好不要這樣做。更多的介紹請(qǐng)看下面內(nèi)容。

    (21)

    abstract (可選): 用于在<union-subclass>的繼承結(jié)構(gòu) (hierarchies)中標(biāo)識(shí)抽象超類。

    (22)

    entity-name (可選, 默認(rèn)為類名): 顯式指定實(shí)體名

    若指明的持久化類實(shí)際上是一個(gè)接口,這也是完全可以接受的。 之后你可以用<subclass>來(lái)指定該接口的實(shí)際實(shí)現(xiàn)類。 你可以持久化任何static(靜態(tài)的)內(nèi)部類。 你應(yīng)該使用標(biāo)準(zhǔn)的類名格式來(lái)指定類名,比如:Foo$Bar

    不可變類,mutable="false"不可以被應(yīng)用程序更新或者刪除。 這可以讓Hibernate做一些小小的性能優(yōu)化。

    可選的proxy屬性允許延遲加載類的持久化實(shí)例。 Hibernate開始會(huì)返回實(shí)現(xiàn)了這個(gè)命名接口的CGLIB代理。當(dāng)代理的某個(gè)方法被實(shí)際調(diào)用的時(shí)候, 真實(shí)的持久化對(duì)象才會(huì)被裝載。參見下面的“用于延遲裝載的代理”。

    Implicit (隱式)的多態(tài)是指,如果查詢時(shí)給出的是任何超類、該類實(shí)現(xiàn)的接口或者該類的 名字,都會(huì)返回這個(gè)類的實(shí)例;如果查詢中給出的是子類的名字,則會(huì)返回子類的實(shí)例。 Explicit (顯式)的多態(tài)是指,只有在查詢時(shí)給出明確的該類名字時(shí)才會(huì)返回這個(gè)類的實(shí)例; 同時(shí)只有在這個(gè)<class>的定義中作為<subclass> 或者<joined-subclass>出現(xiàn)的子類,才會(huì)可能返回。 在大多數(shù)情況下,默認(rèn)的polymorphism="implicit"都是合適的。 顯式的多態(tài)在有兩個(gè)不同的類映射到同一個(gè)表的時(shí)候很有用。(允許一個(gè)“輕型”的類,只包含部分表字段)。

    persister屬性可以讓你定制這個(gè)類使用的持久化策略。 你可以指定你自己實(shí)現(xiàn) org.hibernate.persister.EntityPersister的子類,你甚至可以完全從頭開始編寫一個(gè) org.hibernate.persister.ClassPersister接口的實(shí)現(xiàn), 比如是用儲(chǔ)存過程調(diào)用、序列化到文件或者LDAP數(shù)據(jù)庫(kù)來(lái)實(shí)現(xiàn)。 參閱org.hibernate.test.CustomPersister,這是一個(gè)簡(jiǎn)單的例子 (“持久化”到一個(gè)Hashtable)。

    請(qǐng)注意dynamic-updatedynamic-insert的設(shè)置并不會(huì)繼承到子類, 所以在<subclass>或者<joined-subclass>元素中可能 需要再次設(shè)置。這些設(shè)置是否能夠提高效率要視情形而定。請(qǐng)用你的智慧決定是否使用。

    使用select-before-update通常會(huì)降低性能。如果你重新連接一個(gè)脫管(detache)對(duì)象實(shí)例 到一個(gè)Session中時(shí),它可以防止數(shù)據(jù)庫(kù)不必要的觸發(fā)update。 這就很有用了。

    如果你打開了dynamic-update,你可以選擇幾種樂觀鎖定的策略:

    • version(版本檢查) 檢查version/timestamp字段

    • all(全部) 檢查全部字段

    • dirty(臟檢查)只檢察修改過的字段

    • none(不檢查)不使用樂觀鎖定

    我們非常強(qiáng)烈建議你在Hibernate中使用version/timestamp字段來(lái)進(jìn)行樂觀鎖定。 對(duì)性能來(lái)說,這是最好的選擇,并且這也是唯一能夠處理在session外進(jìn)行操作的策略(例如: 在使用Session.merge()的時(shí)候)。

    對(duì)Hibernate映射來(lái)說視圖和表是沒有區(qū)別的,這是因?yàn)樗鼈冊(cè)跀?shù)據(jù)層都是透明的( 注意:一些數(shù)據(jù)庫(kù)不支持視圖屬性,特別是更新的時(shí)候)。有時(shí)你想使用視圖,但卻不能在數(shù)據(jù)庫(kù) 中創(chuàng)建它(例如:在遺留的schema中)。這樣的話,你可以映射一個(gè)不可變的(immutable)并且是 只讀的實(shí)體到一個(gè)給定的SQL子查詢表達(dá)式:

    <class name="Summary">
    <subselect>
    select item.name, max(bid.amount), count(*)
    from item
    join bid on bid.item_id = item.id
    group by item.name
    </subselect>
    <synchronize table="item"/>
    <synchronize table="bid"/>
    <id name="name"/>
    ...
    </class>

    定義這個(gè)實(shí)體用到的表為同步(synchronize),確保自動(dòng)刷新(auto-flush)正確執(zhí)行, 并且依賴原實(shí)體的查詢不會(huì)返回過期數(shù)據(jù)。<subselect>在屬性元素 和一個(gè)嵌套映射元素中都可見。

    6.1.4. id

    被映射的類必須定義對(duì)應(yīng)數(shù)據(jù)庫(kù)表主鍵字段。大多數(shù)類有一個(gè)JavaBeans風(fēng)格的屬性, 為每一個(gè)實(shí)例包含唯一的標(biāo)識(shí)。<id> 元素定義了該屬性到數(shù)據(jù)庫(kù)表主鍵字段的映射。

    <id
    name="propertyName"                                          (1)
    type="typename"                                              (2)
    column="column_name"                                         (3)
    unsaved-value="null|any|none|undefined|id_value"             (4)
    access="field|property|ClassName"                            (5)
    node="element-name|@attribute-name|element/@attribute|.">
    <generator class="generatorClass"/>
    </id>
    (1)

    name (可選): 標(biāo)識(shí)屬性的名字。

    (2)

    type (可選): 標(biāo)識(shí)Hibernate類型的名字。

    (3)

    column (可選 - 默認(rèn)為屬性名): 主鍵字段的名字。

    (4)

    unsaved-value (可選 - 默認(rèn)為一個(gè)字段判斷(sensible)的值): 一個(gè)特定的標(biāo)識(shí)屬性值,用來(lái)標(biāo)志該實(shí)例是剛剛創(chuàng)建的,尚未保存。 這可以把這種實(shí)例和從以前的session中裝載過(可能又做過修改--譯者注) 但未再次持久化的實(shí)例區(qū)分開來(lái)。

    (5)

    access (可選 - 默認(rèn)為property): Hibernate用來(lái)訪問屬性值的策略。

    如果 name屬性不存在,會(huì)認(rèn)為這個(gè)類沒有標(biāo)識(shí)屬性。

    unsaved-value 屬性很重要!如果你的類的標(biāo)識(shí)屬性不是默認(rèn)為 正常的Java默認(rèn)值(null或零),你應(yīng)該指定正確的默認(rèn)值。

    還有一個(gè)另外的<composite-id>定義可以訪問舊式的多主鍵數(shù)據(jù)。 我們強(qiáng)烈不建議使用這種方式。

    6.1.4.1. Generator

    可選的<generator>子元素是一個(gè)Java類的名字, 用來(lái)為該持久化類的實(shí)例生成唯一的標(biāo)識(shí)。如果這個(gè)生成器實(shí)例需要某些配置值或者初始化參數(shù), 用<param>元素來(lái)傳遞。

    <id name="id" type="long" column="cat_id">
    <generator class="org.hibernate.id.TableHiLoGenerator">
    <param name="table">uid_table</param>
    <param name="column">next_hi_value_column</param>
    </generator>
    </id>

    所有的生成器都實(shí)現(xiàn)net.sf.hibernate.id.IdentifierGenerator接口。 這是一個(gè)非常簡(jiǎn)單的接口;某些應(yīng)用程序可以選擇提供他們自己特定的實(shí)現(xiàn)。當(dāng)然, Hibernate提供了很多內(nèi)置的實(shí)現(xiàn)。下面是一些內(nèi)置生成器的快捷名字:

    increment

    用于為long, short或者int類型生成 唯一標(biāo)識(shí)。只有在沒有其他進(jìn)程往同一張表中插入數(shù)據(jù)時(shí)才能使用。 在集群下不要使用。

    identity

    對(duì)DB2,MySQL, MS SQL Server, Sybase和HypersonicSQL的內(nèi)置標(biāo)識(shí)字段提供支持。 返回的標(biāo)識(shí)符是long, short 或者int類型的。

    sequence

    在DB2,PostgreSQL, Oracle, SAP DB, McKoi中使用序列(sequence), 而在Interbase中使用生成器(generator)。返回的標(biāo)識(shí)符是long, short或者 int類型的。

    hilo

    使用一個(gè)高/低位算法高效的生成long, short 或者 int類型的標(biāo)識(shí)符。給定一個(gè)表和字段(默認(rèn)分別是是 hibernate_unique_keynext_hi)作為高位值的來(lái)源。 高/低位算法生成的標(biāo)識(shí)符只在一個(gè)特定的數(shù)據(jù)庫(kù)中是唯一的。

    seqhilo

    使用一個(gè)高/低位算法來(lái)高效的生成long, short 或者 int類型的標(biāo)識(shí)符,給定一個(gè)數(shù)據(jù)庫(kù)序列(sequence)的名字。

    uuid

    用一個(gè)128-bit的UUID算法生成字符串類型的標(biāo)識(shí)符, 這在一個(gè)網(wǎng)絡(luò)中是唯一的(使用了IP地址)。UUID被編碼為一個(gè)32位16進(jìn)制數(shù)字的字符串。

    guid

    在MS SQL Server 和 MySQL 中使用數(shù)據(jù)庫(kù)生成的GUID字符串。

    native

    根據(jù)底層數(shù)據(jù)庫(kù)的能力選擇identity, sequence 或者hilo中的一個(gè)。

    assigned

    讓應(yīng)用程序在save()之前為對(duì)象分配一個(gè)標(biāo)示符。這是 <generator>元素沒有指定時(shí)的默認(rèn)生成策略。

    select

    通過數(shù)據(jù)庫(kù)觸發(fā)器選擇一些唯一主鍵的行并返回主鍵值來(lái)分配一個(gè)主鍵。

    foreign

    使用另外一個(gè)相關(guān)聯(lián)的對(duì)象的標(biāo)識(shí)符。通常和<one-to-one>聯(lián)合起來(lái)使用。

     

    6.1.4.2. 高/低位算法(Hi/Lo Algorithm)

    hiloseqhilo生成器給出了兩種hi/lo算法的實(shí)現(xiàn), 這是一種很令人滿意的標(biāo)識(shí)符生成算法。第一種實(shí)現(xiàn)需要一個(gè)“特殊”的數(shù)據(jù)庫(kù)表來(lái)保存下一個(gè)可用的“hi”值。 第二種實(shí)現(xiàn)使用一個(gè)Oracle風(fēng)格的序列(在被支持的情況下)。

    <id name="id" type="long" column="cat_id">
    <generator class="hilo">
    <param name="table">hi_value</param>
    <param name="column">next_value</param>
    <param name="max_lo">100</param>
    </generator>
    </id>
    <id name="id" type="long" column="cat_id">
    <generator class="seqhilo">
    <param name="sequence">hi_value</param>
    <param name="max_lo">100</param>
    </generator>
    </id>

    很不幸,你在為Hibernate自行提供Connection時(shí)無(wú)法使用hilo。 當(dāng)Hibernate使用JTA獲取應(yīng)用服務(wù)器的數(shù)據(jù)源連接時(shí),你必須正確地配置 hibernate.transaction.manager_lookup_class

    6.1.4.3. UUID算法(UUID Algorithm )

    UUID包含:IP地址,JVM的啟動(dòng)時(shí)間(精確到1/4秒),系統(tǒng)時(shí)間和一個(gè)計(jì)數(shù)器值(在JVM中唯一)。 在Java代碼中不可能獲得MAC地址或者內(nèi)存地址,所以這已經(jīng)是我們?cè)诓皇褂肑NI的前提下的能做的最好實(shí)現(xiàn)了。

    6.1.4.4. 標(biāo)識(shí)字段和序列(Identity columns and Sequences)

    對(duì)于內(nèi)部支持標(biāo)識(shí)字段的數(shù)據(jù)庫(kù)(DB2,MySQL,Sybase,MS SQL),你可以使用identity關(guān)鍵字生成。 對(duì)于內(nèi)部支持序列的數(shù)據(jù)庫(kù)(DB2,Oracle, PostgreSQL, Interbase, McKoi,SAP DB), 你可以使用sequence風(fēng)格的關(guān)鍵字生成。 這兩種方式對(duì)于插入一個(gè)新的對(duì)象都需要兩次SQL查詢。

    <id name="id" type="long" column="person_id">
    <generator class="sequence">
    <param name="sequence">person_id_sequence</param>
    </generator>
    </id>
    <id name="id" type="long" column="person_id" unsaved-value="0">
    <generator class="identity"/>
    </id>

    對(duì)于跨平臺(tái)開發(fā),native策略會(huì)從identity, sequencehilo中進(jìn)行選擇,選擇哪一個(gè),這取決于底層數(shù)據(jù)庫(kù)的支持能力。

    6.1.4.5. 程序分配的標(biāo)識(shí)符(Assigned Identifiers)

    如果你需要應(yīng)用程序分配一個(gè)標(biāo)示符(而非Hibernate來(lái)生成),你可以使用assigned 生成器。這種特殊的生成器會(huì)使用已經(jīng)分配給對(duì)象的標(biāo)識(shí)符屬性的標(biāo)識(shí)符值。 這個(gè)生成器使用一個(gè)自然鍵(natural key,有商業(yè)意義的列-譯注)作為主鍵,而不是使用一個(gè)代理鍵( surrogate key,沒有商業(yè)意義的列-譯注)。

    當(dāng)選擇assigned生成器時(shí),除非有一個(gè)version或timestamp屬性,或者你定義了 Interceptor.isUnsaved(),否則需要讓Hiberante使用 unsaved-value="undefined",強(qiáng)制Hibernatet查詢數(shù)據(jù)庫(kù)來(lái)確定一個(gè)實(shí)例是瞬時(shí)的(transient) 還是脫管的(detached)。

    6.1.4.6. 觸發(fā)器實(shí)現(xiàn)的主鍵生成器(Primary keys assigned by triggers)

    僅僅用于遺留的schema中 (Hibernate不能使用觸發(fā)器生成DDL)。

    <id name="id" type="long" column="person_id">
    <generator class="select">
    <param name="key">socialSecurityNumber</param>
    </generator>
    </id>

    在上面的例子中,類定義了一個(gè)命名為socialSecurityNumber的唯一值屬性, 它是一個(gè)自然鍵(natural key),命名為person_id的代理鍵(surrogate key) 的值由觸發(fā)器生成。

    6.1.5. composite-id

    <composite-id
    name="propertyName"
    class="ClassName"
    unsaved-value="undefined|any|none"
    access="field|property|ClassName"
    node="element-name|."
    >
    <key-property name="propertyName" type="typename" column="column_name"/>
    <key-many-to-one name="propertyName class="ClassName" column="column_name"/>
    ......
    </composite-id>

    For a table with a composite key, you may map multiple properties of the class as identifier properties. The <composite-id> element accepts <key-property> property mappings and <key-many-to-one> mappings as child elements.

    如果表使用聯(lián)合主鍵,你可以映射類的多個(gè)屬性為標(biāo)識(shí)符屬性。 <composite-id>元素接受<key-property> 屬性映射和<key-many-to-one>屬性映射作為子元素。

    <composite-id>
    <key-property name="medicareNumber"/>
    <key-property name="dependent"/>
    </composite-id>

    你的持久化類必須重載equals()hashCode()方法,來(lái)實(shí)現(xiàn)組合的標(biāo)識(shí)符的相等判斷。 實(shí)現(xiàn)Serializable接口也是必須的。

    不幸的是,這種組合關(guān)鍵字的方法意味著一個(gè)持久化類是它自己的標(biāo)識(shí)。除了對(duì)象自己之外, 沒有什么方便的“把手”可用。你必須自己初始化持久化類的實(shí)例,在使用組合關(guān)鍵字load() 持久化狀態(tài)之前,必須填充他的聯(lián)合屬性。我們會(huì)在第 9.4 節(jié) “組件作為聯(lián)合標(biāo)識(shí)符(Components as composite identifiers)”章中說明一種 更加便捷的方法,把聯(lián)合標(biāo)識(shí)實(shí)現(xiàn)為一個(gè)獨(dú)立的類,下面描述的屬性只對(duì)這種備用方法有效:

    • name (可選):一個(gè)組件類型,持有復(fù)合標(biāo)識(shí)(參見下一節(jié))。

    • class (可選 - 默認(rèn)為通過反射(reflection)得到的屬性類型) : 作為聯(lián)合標(biāo)識(shí)的組件類名(參見下一節(jié))。

    • unsaved-value (可選 - 默認(rèn)為 undefined): 如果設(shè)置為any,就表示瞬時(shí)(transient)實(shí)例應(yīng)該被重新初始化,或者如果 設(shè)置為none,則表示該實(shí)例是脫管對(duì)象。最好在所有的情況下都保持默認(rèn)的值。

    6.1.6. 鑒別器(discriminator)

    在"一棵對(duì)象繼承樹對(duì)應(yīng)一個(gè)表"的策略中,<discriminator>元素是必需的, 它定義了表的鑒別器字段。鑒別器字段包含標(biāo)志值,用于告知持久化層應(yīng)該為某個(gè)特定的行創(chuàng)建哪一個(gè)子類的實(shí)例。 如下這些受到限制的類型可以使用: string, character, integer, byte, short, boolean, yes_no, true_false.

    <discriminator
    column="discriminator_column"                      (1)
    type="discriminator_type"                          (2)
    force="true|false"                                 (3)
    insert="true|false"                                (4)
    formula="arbitrary sql expression"                 (5)
    />
    (1)

    column (可選 - 默認(rèn)為 class) 鑒別器字段的名字

    (2)

    type (可選 - 默認(rèn)為 string) 一個(gè)Hibernate字段類型的名字

    (3)

    force(強(qiáng)制) (可選 - 默認(rèn)為 false) "強(qiáng)制"Hibernate指定允許的鑒別器值,就算取得的所有實(shí)例都是根類的。

    (4)

    insert (可選 - 默認(rèn)為true) 如果你的鑒別器字段也是映射為復(fù)合標(biāo)識(shí)(composite identifier)的一部分,則需將 這個(gè)值設(shè)為false。(告訴Hibernate在做SQL INSERT 時(shí)不包含該列)

    (5)

    formula (可選) 一個(gè)SQL表達(dá)式,在類型判斷(判斷是父類還是具體子類-譯注)時(shí)執(zhí)行。可用于基于內(nèi)容的鑒別器。

    鑒別器字段的實(shí)際值是根據(jù)<class><subclass>元素中 的discriminator-value屬性得來(lái)的。

    force屬性僅僅是在表包含一些未指定應(yīng)該映射到哪個(gè)持久化類的時(shí)候才是有用的。 這種情況不會(huì)經(jīng)常遇到。

    使用formula屬性你可以定義一個(gè)SQL表達(dá)式,用來(lái)判斷一個(gè)行數(shù)據(jù)的類型。

    <discriminator
    formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0 else 1 end"
    type="integer"/>

    6.1.7. 版本(version)(可選)

    <version>元素是可選的,表明表中包含附帶版本信息的數(shù)據(jù)。 這在你準(zhǔn)備使用 長(zhǎng)事務(wù)(long transactions)的時(shí)候特別有用。(見后)

    <version
    column="version_column"                                      (1)
    name="propertyName"                                          (2)
    type="typename"                                              (3)
    access="field|property|ClassName"                            (4)
    unsaved-value="null|negative|undefined"                      (5)
    node="element-name|@attribute-name|element/@attribute|."
    />
    (1)

    column (可選 - 默認(rèn)為屬性名): 指定持有版本號(hào)的字段名。

    (2)

    name: 持久化類的屬性名。

    (3)

    type (可選 - 默認(rèn)是 integer): 版本號(hào)的類型。

    (4)

    access (可選 - 默認(rèn)是 property): Hibernate用于訪問屬性值的策略。

    (5)

    unsaved-value (可選 - 默認(rèn)是undefined): 用于標(biāo)明某個(gè)實(shí)例時(shí)剛剛被實(shí)例化的(尚未保存)版本屬性值,依靠這個(gè)值就可以把這種情況 和已經(jīng)在先前的session中保存或裝載的脫管(detached)實(shí)例區(qū)分開來(lái)。 (undefined指明使用標(biāo)識(shí)屬性值進(jìn)行判斷。)

    版本號(hào)必須是以下類型:long, integer, short, timestamp或者calendar

    一個(gè)脫管(detached)實(shí)例的version或timestamp不能為空(null),因?yàn)镠ibernate不管 unsaved-value指定為何種策略,它將分離任何屬性為空的version或timestamp 實(shí)例為瞬時(shí)(transient)實(shí)例。 避免Hibernate中的傳遞重附(transitive reattachment)問題的一個(gè)簡(jiǎn)單方法是 定義一個(gè)不能為空的version或timestamp屬性,特別是在人們使用程序分配的標(biāo)識(shí)符(assigned identifiers) 或復(fù)合主鍵時(shí)非常有用!

    6.1.8. timestamp (optional)

    可選的<timestamp>元素指明了表中包含時(shí)間戳數(shù)據(jù)。 這用來(lái)作為版本的替代。時(shí)間戳本質(zhì)上是一種對(duì)樂觀鎖定的一種不是特別安全的實(shí)現(xiàn)。當(dāng)然, 有時(shí)候應(yīng)用程序可能在其他方面使用時(shí)間戳。

    <timestamp
    column="timestamp_column"                                    (1)
    name="propertyName"                                          (2)
    access="field|property|ClassName"                            (3)
    unsaved-value="null|undefined"                               (4)
    node="element-name|@attribute-name|element/@attribute|."
    />
    (1)

    column (可選 - 默認(rèn)為屬性名): 持有時(shí)間戳的字段名。

    (2)

    name: 在持久化類中的JavaBeans風(fēng)格的屬性名, 其Java類型是 Date 或者 Timestamp的。

    (3)

    access (可選 - 默認(rèn)是 property): Hibernate用于訪問屬性值的策略。

    (4)

    unsaved-value (可選 - 默認(rèn)是null): 用于標(biāo)明某個(gè)實(shí)例時(shí)剛剛被實(shí)例化的(尚未保存)版本屬性值,依靠這個(gè)值就可以把這種情況和 已經(jīng)在先前的session中保存或裝載的脫管(detached)實(shí)例區(qū)分開來(lái)。(undefined 指明使用標(biāo)識(shí)屬性值進(jìn)行這種判斷。)

    注意,<timestamp><version type="timestamp">是等價(jià)的。

    6.1.9. property

    <property>元素為類定義了一個(gè)持久化的,JavaBean風(fēng)格的屬性。

    <property
    name="propertyName"                                          (1)
    column="column_name"                                         (2)
    type="typename"                                              (3)
    update="true|false"                                          (4)
    insert="true|false"                                          (4)
    formula="arbitrary SQL expression"                           (5)
    access="field|property|ClassName"                            (6)
    lazy="true|false"                                            (7)
    unique="true|false"                                          (8)
    not-null="true|false"                                        (9)
    optimistic-lock="true|false"                                 (10)
    node="element-name|@attribute-name|element/@attribute|."
    />
    (1)

    name: 屬性的名字,以小寫字母開頭。

    (2)

    column (可選 - 默認(rèn)為屬性名字): 對(duì)應(yīng)的數(shù)據(jù)庫(kù)字段名。 也可以通過嵌套的<column>元素指定。

    (3)

    type (可選): 一個(gè)Hibernate類型的名字。

    (4)

    update, insert (可選 - 默認(rèn)為 true) : 表明用于UPDATE 和/或 INSERT 的SQL語(yǔ)句中是否包含這個(gè)被映射了的字段。這二者如果都設(shè)置為false 則表明這是一個(gè)“外源性(derived)”的屬性,它的值來(lái)源于映射到同一個(gè)(或多個(gè)) 字段的某些其他屬性,或者通過一個(gè)trigger(觸發(fā)器)或其他程序。

    (5)

    formula (可選): 一個(gè)SQL表達(dá)式,定義了這個(gè)計(jì)算 (computed) 屬性的值。計(jì)算屬性沒有和它對(duì)應(yīng)的數(shù)據(jù)庫(kù)字段。

    (6)

    access (可選 - 默認(rèn)值為 property): Hibernate用來(lái)訪問屬性值的策略。

    (7)

    lazy (可選 - 默認(rèn)為 false): 指定 指定實(shí)例變量第一次被訪問時(shí),這個(gè)屬性是否延遲抓取(fetched lazily)( 需要運(yùn)行時(shí)字節(jié)碼增強(qiáng))。

    (8)

    unique (可選): 使用DDL為該字段添加唯一的約束。 此外,這也可以用作property-ref的目標(biāo)屬性。

    (9)

    not-null (可選): 使用DDL為該字段添加可否為空(nullability)的約束。

    (10)

    optimistic-lock (可選 - 默認(rèn)為 true): 指定這個(gè)屬性在做更新時(shí)是否需要獲得樂觀鎖定(optimistic lock)。 換句話說,它決定這個(gè)屬性發(fā)生臟數(shù)據(jù)時(shí)版本(version)的值是否增長(zhǎng)。

    typename可以是如下幾種:

    1. Hibernate基礎(chǔ)類型之一(比如:integer, string, character,date, timestamp, float, binary, serializable, object, blob)。

    2. 一個(gè)Java類的名字,這個(gè)類屬于一種默認(rèn)基礎(chǔ)類型 (比如: int, float,char, java.lang.String, java.util.Date, java.lang.Integer, java.sql.Clob)。

    3. 一個(gè)可以序列化的Java類的名字。

    4. 一個(gè)自定義類型的類的名字。(比如: com.illflow.type.MyCustomType)。

    如果你沒有指定類型,Hibernarte會(huì)使用反射來(lái)得到這個(gè)名字的屬性,以此來(lái)猜測(cè)正確的Hibernate類型。 Hibernate會(huì)按照規(guī)則2,3,4的順序?qū)傩宰x取器(getter方法)的返回類進(jìn)行解釋。然而,這還不夠。 在某些情況下你仍然需要type屬性。(比如,為了區(qū)別Hibernate.DATEHibernate.TIMESTAMP,或者為了指定一個(gè)自定義類型。)

    access屬性用來(lái)讓你控制Hibernate如何在運(yùn)行時(shí)訪問屬性。在默認(rèn)情況下, Hibernate會(huì)使用屬性的get/set方法對(duì)(pair)。如果你指明access="field", Hibernate會(huì)忽略get/set方法對(duì),直接使用反射來(lái)訪問成員變量。你也可以指定你自己的策略, 這就需要你自己實(shí)現(xiàn)org.hibernate.property.PropertyAccessor接口, 再在access中設(shè)置你自定義策略類的名字。

    衍生屬性(derive propertie)是一個(gè)特別強(qiáng)大的特征。這些屬性應(yīng)該定義為只讀,屬性值在裝載時(shí)計(jì)算生成。 你用一個(gè)SQL表達(dá)式生成計(jì)算的結(jié)果,它會(huì)在這個(gè)實(shí)例轉(zhuǎn)載時(shí)翻譯成一個(gè)SQL查詢的SELECT 子查詢語(yǔ)句。

    <property name="totalPrice"
    formula="( SELECT SUM (li.quantity*p.price) FROM LineItem li, Product p
    WHERE li.productId = p.productId
    AND li.customerId = customerId
    AND li.orderNumber = orderNumber )"/>

    注意,你可以使用實(shí)體自己的表,而不用為這個(gè)特別的列定義別名( 上面例子中的customerId)。同時(shí)注意,如果你不喜歡使用屬性, 你可以使用嵌套的<formula>映射元素。

    6.1.10. 多對(duì)一(many-to-one)

    通過many-to-one元素,可以定義一種常見的與另一個(gè)持久化類的關(guān)聯(lián)。 這種關(guān)系模型是多對(duì)一關(guān)聯(lián)(實(shí)際上是一個(gè)對(duì)象引用-譯注):這個(gè)表的一個(gè)外鍵引用目標(biāo)表的 主鍵字段。

    <many-to-one
    name="propertyName"                                          (1)
    column="column_name"                                         (2)
    class="ClassName"                                            (3)
    cascade="cascade_style"                                      (4)
    fetch="join|select"                                          (5)
    update="true|false"                                          (6)
    insert="true|false"                                          (6)
    property-ref="propertyNameFromAssociatedClass"               (7)
    access="field|property|ClassName"                            (8)
    unique="true|false"                                          (9)
    not-null="true|false"                                        (10)
    optimistic-lock="true|false"                                 (11)
    lazy="true|proxy|false"                                      (12)
    not-found="ignore|exception"                                 (13)
    entity-name="EntityName"                                     (14)
    node="element-name|@attribute-name|element/@attribute|."
    embed-xml="true|false"
    />
    (1)

    name: 屬性名。

    (2)

    column (可選): 外間字段名。它也可以通過嵌套的 <column>元素指定。

    (3)

    class (可選 - 默認(rèn)是通過反射得到屬性類型): 關(guān)聯(lián)的類的名字。

    (4)

    cascade(級(jí)聯(lián)) (可選): 指明哪些操作會(huì)從父對(duì)象級(jí)聯(lián)到關(guān)聯(lián)的對(duì)象。

    (5)

    fetch (可選 - 默認(rèn)為 select): 在外連接抓取(outer-join fetching)和序列選擇抓取(sequential select fetching)兩者中選擇其一。

    (6)

    update, insert (可選 - defaults to true) 指定對(duì)應(yīng)的字段是否包含在用于UPDATE 和/或 INSERT 的SQL語(yǔ)句中。如果二者都是false,則這是一個(gè)純粹的 “外源性(derived)”關(guān)聯(lián),它的值是通過映射到同一個(gè)(或多個(gè))字段的某些其他屬性得到 或者通過trigger(觸發(fā)器)、或其他程序。

    (7)

    property-ref: (可選) 指定關(guān)聯(lián)類的一個(gè)屬性,這個(gè)屬性將會(huì)和本外鍵相對(duì)應(yīng)。 如果沒有指定,會(huì)使用對(duì)方關(guān)聯(lián)類的主鍵。

    (8)

    access (可選 - 默認(rèn)是 property): Hibernate用來(lái)訪問屬性的策略。

    (9)

    unique (可選): 使用DDL為外鍵字段生成一個(gè)唯一約束。此外, 這也可以用作property-ref的目標(biāo)屬性。這使關(guān)聯(lián)同時(shí)具有 一對(duì)一的效果。

    (10)

    not-null (可選): 使用DDL為外鍵字段生成一個(gè)非空約束。

    (11)

    optimistic-lock (可選 - 默認(rèn)為 true): 指定這個(gè)屬性在做更新時(shí)是否需要獲得樂觀鎖定(optimistic lock)。 換句話說,它決定這個(gè)屬性發(fā)生臟數(shù)據(jù)時(shí)版本(version)的值是否增長(zhǎng)。

    (12)

    lazy (可選 - 默認(rèn)為 proxy): 默認(rèn)情況下,單點(diǎn)關(guān)聯(lián)是經(jīng)過代理的。lazy="true"指定此屬性應(yīng)該在實(shí)例變量第一次被訪問時(shí)應(yīng)該延遲抓取(fetche lazily)(需要運(yùn)行時(shí)字節(jié)碼的增強(qiáng))。 lazy="false"指定此關(guān)聯(lián)總是被預(yù)先抓取。

    (13)

    not-found (可選 - 默認(rèn)為 exception): 指定外鍵引用的數(shù)據(jù)不存在時(shí)如何處理: ignore會(huì)將數(shù)據(jù)不存在作為關(guān)聯(lián)到一個(gè)空對(duì)象(null)處理。

    (14)

    entity-name (optional): 被關(guān)聯(lián)的類的實(shí)體名。

    cascade屬性設(shè)置為除了none以外任何有意義的值, 它將把特定的操作傳播到關(guān)聯(lián)對(duì)象中。這個(gè)值就代表著Hibernate基本操作的名稱, persist, merge, delete, save-update, evict, replicate, lock, refresh, 以及特別的值delete-orphanall,并且可以用逗號(hào)分隔符 來(lái)合并這些操作,例如,cascade="persist,merge,evict"cascade="all,delete-orphan"。更全面的解釋請(qǐng)參考第 11.11 節(jié) “傳播性持久化(transitive persistence)”.

    一個(gè)典型的簡(jiǎn)單many-to-one定義例子:

    <many-to-one name="product" class="Product" column="PRODUCT_ID"/>

    property-ref屬性只應(yīng)該用來(lái)對(duì)付老舊的數(shù)據(jù)庫(kù)系統(tǒng), 可能有外鍵指向?qū)Ψ疥P(guān)聯(lián)表的是個(gè)非主鍵字段(但是應(yīng)該是一個(gè)惟一關(guān)鍵字)的情況下。 這是一種十分丑陋的關(guān)系模型。比如說,假設(shè)Product類有一個(gè)惟一的序列號(hào), 它并不是主鍵。(unique屬性控制Hibernate通過SchemaExport工具生成DDL的過程。)

    <property name="serialNumber" unique="true" type="string" column="SERIAL_NUMBER"/>

    那么關(guān)于OrderItem 的映射可能是:

    <many-to-one name="product" property-ref="serialNumber" column="PRODUCT_SERIAL_NUMBER"/>

    當(dāng)然,我們決不鼓勵(lì)這種用法。

    如果被引用的唯一主鍵由關(guān)聯(lián)實(shí)體的多個(gè)屬性組成,你應(yīng)該在名稱為<properties>的元素 里面映射所有關(guān)聯(lián)的屬性。

    6.1.11. 一對(duì)一

    持久化對(duì)象之間一對(duì)一的關(guān)聯(lián)關(guān)系是通過one-to-one元素定義的。

    <one-to-one
    name="propertyName"                                          (1)
    class="ClassName"                                            (2)
    cascade="cascade_style"                                      (3)
    constrained="true|false"                                     (4)
    fetch="join|select"                                          (5)
    property-ref="propertyNameFromAssociatedClass"               (6)
    access="field|property|ClassName"                            (7)
    formula="any SQL expression"                                 (8)
    lazy="true|proxy|false"                                      (9)
    entity-name="EntityName"                                     (10)
    node="element-name|@attribute-name|element/@attribute|."
    embed-xml="true|false"
    />
    (1)

    name: 屬性的名字。

    (2)

    class (可選 - 默認(rèn)是通過反射得到的屬性類型):被關(guān)聯(lián)的類的名字。

    (3)

    cascade(級(jí)聯(lián)) (可選) 表明操作是否從父對(duì)象級(jí)聯(lián)到被關(guān)聯(lián)的對(duì)象。

    (4)

    constrained(約束) (可選) 表明該類對(duì)應(yīng)的表對(duì)應(yīng)的數(shù)據(jù)庫(kù)表,和被關(guān)聯(lián)的對(duì)象所對(duì)應(yīng)的數(shù)據(jù)庫(kù)表之間,通過一個(gè)外鍵引用對(duì)主鍵進(jìn)行約束。 這個(gè)選項(xiàng)影響save()delete()在級(jí)聯(lián)執(zhí)行時(shí)的先后順序以及 決定該關(guān)聯(lián)能否被委托(也在schema export tool中被使用).

    (5)

    fetch (可選 - 默認(rèn)設(shè)置為選擇): 在外連接抓取或者序列選擇抓取選擇其一.

    (6)

    property-ref: (可選) 指定關(guān)聯(lián)類的屬性名,這個(gè)屬性將會(huì)和本類的主鍵相對(duì)應(yīng)。如果沒有指定,會(huì)使用對(duì)方關(guān)聯(lián)類的主鍵。

    (7)

    access (可選 - 默認(rèn)是 property): Hibernate用來(lái)訪問屬性的策略。

    (8)

    formula (可選):絕大多數(shù)一對(duì)一的關(guān)聯(lián)都指向其實(shí)體的主鍵。在一些少見的情況中, 你可能會(huì)指向其他的一個(gè)或多個(gè)字段,或者是一個(gè)表達(dá)式,這些情況下,你可以用一個(gè)SQL公式來(lái)表示。 (可以在org.hibernate.test.onetooneformula找到例子)

    (9)

    lazy (可選 - 默認(rèn)為 proxy): 默認(rèn)情況下,單點(diǎn)關(guān)聯(lián)是經(jīng)過代理的。lazy="true"指定此屬性應(yīng)該在實(shí)例變量第一次被訪問時(shí)應(yīng)該延遲抓取(fetche lazily)(需要運(yùn)行時(shí)字節(jié)碼的增強(qiáng))。 lazy="false"指定此關(guān)聯(lián)總是被預(yù)先抓取。注意,如果constrained="false", 不可能使用代理,Hibernate會(huì)采取預(yù)先抓取!

    (10)

    entity-name (可選): 被關(guān)聯(lián)的類的實(shí)體名。

    有兩種不同的一對(duì)一關(guān)聯(lián):

    • 主鍵關(guān)聯(lián)

    • 惟一外鍵關(guān)聯(lián)

    主鍵關(guān)聯(lián)不需要額外的表字段;如果兩行是通過這種一對(duì)一關(guān)系相關(guān)聯(lián)的,那么這兩行就共享同樣的主關(guān)鍵字值。所以如果你希望兩個(gè)對(duì)象通過主鍵一對(duì)一關(guān)聯(lián),你必須確認(rèn)它們被賦予同樣的標(biāo)識(shí)值!

    比如說,對(duì)下面的EmployeePerson進(jìn)行主鍵一對(duì)一關(guān)聯(lián):

    <one-to-one name="person" class="Person"/>
    <one-to-one name="employee" class="Employee" constrained="true"/>

    現(xiàn)在我們必須確保PERSON和EMPLOYEE中相關(guān)的字段是相等的。我們使用一個(gè)被成為foreign的特殊的hibernate標(biāo)識(shí)符生成策略:

    <class name="person" table="PERSON">
    <id name="id" column="PERSON_ID">
    <generator class="foreign">
    <param name="property">employee</param>
    </generator>
    </id>
    ...
    <one-to-one name="employee"
    class="Employee"
    constrained="true"/>
    </class>

    一個(gè)剛剛保存的Person實(shí)例被賦予和該Personemployee屬性所指向的Employee實(shí)例同樣的關(guān)鍵字值。

    另一種方式是一個(gè)外鍵和一個(gè)惟一關(guān)鍵字對(duì)應(yīng),上面的EmployeePerson的例子,如果使用這種關(guān)聯(lián)方式,可以表達(dá)成:

    <many-to-one name="person" class="Person" column="PERSON_ID" unique="true"/>

    如果在Person的映射加入下面幾句,這種關(guān)聯(lián)就是雙向的:

    <one-to-one name"employee" class="Employee" property-ref="person"/>

    6.1.12. 組件(component), 動(dòng)態(tài)組件(dynamic-component)

    <component>元素把子對(duì)象的一些元素與父類對(duì)應(yīng)的表的一些字段映射起來(lái)。 然后組件可以定義它們自己的屬性、組件或者集合。參見后面的“Components”一章。

    <component
    name="propertyName"                 (1)
    class="className"                   (2)
    insert="true|false"                 (3)
    update="true|false"                 (4)
    access="field|property|ClassName"   (5)
    lazy="true|false"                   (6)
    optimistic-lock="true|false"        (7)
    unique="true|false"                 (8)
    node="element-name|."
    >
    <property ...../>
    <many-to-one .... />
    ........
    </component>
    (1)

    name: 屬性名

    (2)

    class (可選 - 默認(rèn)為通過反射得到的屬性類型):組件(子)類的名字。

    (3)

    insert: 被映射的字段是否出現(xiàn)在SQL的INSERT語(yǔ)句中?

    (4)

    update: 被映射的字段是否出現(xiàn)在SQL的UPDATE語(yǔ)句中?

    (5)

    access (可選 - 默認(rèn)是 property): Hibernate用來(lái)訪問屬性的策略。

    (6)

    lazy (可選 - 默認(rèn)是 false): 表明此組件應(yīng)在實(shí)例變量第一次被訪問的時(shí)候延遲加載(需要編譯時(shí)字節(jié)碼裝置器)

    (7)

    optimistic-lock (可選 - 默認(rèn)是 true):表明更新此組件是否需要獲取樂觀鎖。換句話說,當(dāng)這個(gè)屬性變臟時(shí),是否增加版本號(hào)(Version)

    (8)

    unique (可選 - 默認(rèn)是 false):表明組件映射的所有字段上都有唯一性約束

    <property>子標(biāo)簽為子類的一些屬性與表字段之間建立映射。

    <component>元素允許加入一個(gè)<parent>子元素,在組件類內(nèi)部就可以有一個(gè)指向其容器的實(shí)體的反向引用。

    <dynamic-component>元素允許把一個(gè)Map映射為組件,其屬性名對(duì)應(yīng)map的鍵值。 參見第 9.5 節(jié) “動(dòng)態(tài)組件 (Dynamic components)”.

    6.1.13. properties

    <properties> 元素允許定義一個(gè)命名的邏輯分組(grouping)包含一個(gè)類中的多個(gè)屬性。 這個(gè)元素最重要的用處是允許多個(gè)屬性的組合作為property-ref的目標(biāo)(target)。 這也是定義多字段唯一約束的一種方便途徑。

    <properties
    name="logicalName"                  (1)
    insert="true|false"                 (2)
    update="true|false"                 (3)
    optimistic-lock="true|false"        (4)
    unique="true|false"                 (5)
    >
    <property ...../>
    <many-to-one .... />
    ........
    </properties>
    (1)

    name: 分組的邏輯名稱 - 不是 實(shí)際屬性的名稱.

    (2)

    insert: 被映射的字段是否出現(xiàn)在SQL的 INSERT語(yǔ)句中?

    (3)

    update: 被映射的字段是否出現(xiàn)在SQL的 UPDATE語(yǔ)句中?

    (4)

    optimistic-lock (可選 - 默認(rèn)是 true):表明更新此組件是否需要獲取樂觀鎖。換句話說,當(dāng)這個(gè)屬性變臟時(shí),是否增加版本號(hào)(Version)

    (5)

    unique (可選 - 默認(rèn)是 false):表明組件映射的所有字段上都有唯一性約束

    例如,如果我們有如下的<properties>映射:

    <class name="Person">
    <id name="personNumber"/>
    ...
    <properties name="name"
    unique="true" update="false">
    <property name="firstName"/>
    <property name="initial"/>
    <property name="lastName"/>
    </properties>
    </class>

    然后,我們可能有一些遺留的數(shù)據(jù)關(guān)聯(lián),引用 Person表的這個(gè)唯一鍵,而不是主鍵。

    <many-to-one name="person"
    class="Person" property-ref="name">
    <column name="firstName"/>
    <column name="initial"/>
    <column name="lastName"/>
    </many-to-one>

    我們并不推薦這樣使用,除非在映射遺留數(shù)據(jù)的情況下。

    6.1.14. 子類(subclass)

    最后,多態(tài)持久化需要為父類的每個(gè)子類都進(jìn)行定義。對(duì)于“每一棵類繼承樹對(duì)應(yīng)一個(gè)表”的策略來(lái)說,就需要使用<subclass>定義。

    <subclass
    name="ClassName"                              (1)
    discriminator-value="discriminator_value"     (2)
    proxy="ProxyInterface"                        (3)
    lazy="true|false"                             (4)
    dynamic-update="true|false"
    dynamic-insert="true|false"
    entity-name="EntityName"
    node="element-name">
    <property .... />
    .....
    </subclass>
    (1)

    name: 子類的全限定名。

    (2)

    discriminator-value(辨別標(biāo)志) (可選 - 默認(rèn)為類名):一個(gè)用于區(qū)分每個(gè)獨(dú)立的子類的值。

    (3)

    proxy(代理) (可選): 指定一個(gè)類或者接口,在延遲裝載時(shí)作為代理使用。

    (4)

    lazy (可選, 默認(rèn)是true): 設(shè)置為 lazy="false" 禁止使用延遲抓取

    每個(gè)子類都應(yīng)該定義它自己的持久化屬性和子類。 <version><id> 屬性可以從根父類繼承下來(lái)。在一棵繼承樹上的每個(gè)子類都必須定義一個(gè)唯一的discriminator-value。如果沒有指定,就會(huì)使用Java類的全限定名。

    可以在單獨(dú)的映射文件中,直接在hibernate-mapping下定義subclassunion-subclassjoined-subclass映射。這樣你只要增加一個(gè)新的映射文件就可以繼承一棵類繼承樹。你必須在子類的映射中指定extends 屬性來(lái)指定已映射的超類。注意:以前,這個(gè)特性使得映射文件的順序變得很重要。從Hibernate3開始,當(dāng)使用extends關(guān)鍵字的時(shí)候,映射文件的次序便不重要了。而在單一映射文件中,依舊需要保持將超類定義在子類之前這樣的次序。

    <hibernate-mapping>
    <subclass name="DomesticCat" extends="Cat" discriminator-value="D">
    <property name="name" type="string"/>
    </subclass>
    </hibernate-mapping>

    更多關(guān)于繼承映射的信息, 參考 第 10 章 繼承映射(Inheritance Mappings)章節(jié).

    6.1.15. 連接的子類(joined-subclass)

    此外,每個(gè)子類可能被映射到他自己的表中(每個(gè)子類一個(gè)表的策略)。被繼承的狀態(tài)通過和超類的表關(guān)聯(lián)得到。我們使用<joined-subclass>元素。

    <joined-subclass
    name="ClassName"                    (1)
    table="tablename"                   (2)
    proxy="ProxyInterface"              (3)
    lazy="true|false"                   (4)
    dynamic-update="true|false"
    dynamic-insert="true|false"
    schema="schema"
    catalog="catalog"
    extends="SuperclassName"
    persister="ClassName"
    subselect="SQL expression"
    entity-name="EntityName"
    node="element-name">
    <key .... >
    <property .... />
    .....
    </joined-subclass>
    (1)

    name: 子類的全限定名。

    (2)

    table: 子類的表名.

    (3)

    proxy (可選): 指定一個(gè)類或者接口,在延遲裝載時(shí)作為代理使用。

    (4)

    lazy (可選, 默認(rèn)是 true): 設(shè)置為 lazy="false" 禁止使用延遲裝載。

    這種映射策略不需要指定辨別標(biāo)志(discriminator)字段。但是,每一個(gè)子類都必須使用<key>元素指定一個(gè)表字段來(lái)持有對(duì)象的標(biāo)識(shí)符。本章開始的映射可以被用如下方式重寫:

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="eg">
    <class name="Cat" table="CATS">
    <id name="id" column="uid" type="long">
    <generator class="hilo"/>
    </id>
    <property name="birthdate" type="date"/>
    <property name="color" not-null="true"/>
    <property name="sex" not-null="true"/>
    <property name="weight"/>
    <many-to-one name="mate"/>
    <set name="kittens">
    <key column="MOTHER"/>
    <one-to-many class="Cat"/>
    </set>
    <joined-subclass name="DomesticCat" table="DOMESTIC_CATS">
    <key column="CAT"/>
    <property name="name" type="string"/>
    </joined-subclass>
    </class>
    <class name="eg.Dog">
    <!-- mapping for Dog could go here -->
    </class>
    </hibernate-mapping>

    更多關(guān)于繼承映射的信息,參考第 10 章 繼承映射(Inheritance Mappings)

    6.1.16. 聯(lián)合子類(union-subclass)

    第三種選擇是僅僅映射類繼承樹中具體類部分到表中(每個(gè)具體類一張表的策略)。其中,每張表定義了類的所有持久化狀態(tài),包括繼承的狀態(tài)。在 Hibernate 中,并不需要完全顯式地映射這樣的繼承樹。你可以簡(jiǎn)單地使用單獨(dú)的<class>定義映射每個(gè)類。然而,如果你想使用多態(tài)關(guān)聯(lián)(例如,一個(gè)對(duì)類繼承樹中超類的關(guān)聯(lián)),你需要使用<union-subclass>映射。

    <union-subclass
    name="ClassName"                    (1)
    table="tablename"                   (2)
    proxy="ProxyInterface"              (3)
    lazy="true|false"                   (4)
    dynamic-update="true|false"
    dynamic-insert="true|false"
    schema="schema"
    catalog="catalog"
    extends="SuperclassName"
    abstract="true|false"
    persister="ClassName"
    subselect="SQL expression"
    entity-name="EntityName"
    node="element-name">
    <property .... />
    .....
    </union-subclass>
    (1)

    name: 子類的全限定名。

    (2)

    table: 子類的表名

    (3)

    proxy (可選): 指定一個(gè)類或者接口,在延遲裝載時(shí)作為代理使用。

    (4)

    lazy (可選, 默認(rèn)是 true): 設(shè)置為 lazy="false" 禁止使用延遲裝載。

    這種映射策略不需要指定辨別標(biāo)志(discriminator)字段。

    更多關(guān)于繼承映射的信息,參考第 10 章 繼承映射(Inheritance Mappings)

    6.1.17. 連接(join)

    使用 <join> 元素,可以將一個(gè)類的屬性映射到多張表中。

    <join
    table="tablename"                        (1)
    schema="owner"                           (2)
    catalog="catalog"                        (3)
    fetch="join|select"                      (4)
    inverse="true|false"                     (5)
    optional="true|false">                   (6)
    <key ... />
    <property ... />
    ...
    </join>
    (1)

    table: 被連接表的名稱。

    (2)

    schema (可選):覆蓋由根<hibernate-mapping>元素指定的模式名稱。

    (3)

    catalog (可選): 覆蓋由根 <hibernate-mapping>元素指定的目錄名稱。

    (4)

    fetch (可選 - 默認(rèn)是 join): 如果設(shè)置為默認(rèn)值join, Hibernate 將使用一個(gè)內(nèi)連接來(lái)得到這個(gè)類或其超類定義的<join>,而使用一個(gè)外連接來(lái)得到其子類定義的<join>。如果設(shè)置為select,則 Hibernate 將為子類定義的 <join>使用順序選擇。這僅在一行數(shù)據(jù)表示一個(gè)子類的對(duì)象的時(shí)候才會(huì)發(fā)生。對(duì)這個(gè)類和其超類定義的<join>,依然會(huì)使用內(nèi)連接得到。

    (5)

    inverse (可選 - 默認(rèn)是 false): 如果打開,Hibernate 不會(huì)插入或者更新此連接定義的屬性。

    (6)

    optional (可選 - 默認(rèn)是 false): 如果打開,Hibernate 只會(huì)在此連接定義的屬性非空時(shí)插入一行數(shù)據(jù),并且總是使用一個(gè)外連接來(lái)得到這些屬性。

    例如,一個(gè)人(person)的地址(address)信息可以被映射到單獨(dú)的表中(并保留所有屬性的值類型語(yǔ)義):

    <class name="Person"
    table="PERSON">
    <id name="id" column="PERSON_ID">...</id>
    <join table="ADDRESS">
    <key column="ADDRESS_ID"/>
    <property name="address"/>
    <property name="zip"/>
    <property name="country"/>
    </join>
    ...

    此特性常常對(duì)遺留數(shù)據(jù)模型有用,我們推薦表個(gè)數(shù)比類個(gè)數(shù)少,以及細(xì)粒度的領(lǐng)域模型。然而,在單獨(dú)的繼承樹上切換繼承映射策略是有用的,后面會(huì)解釋這點(diǎn)。

    6.1.18. 鍵(key)

    我們目前已經(jīng)見到過<key>元素多次了。 這個(gè)元素在父映射元素定義了對(duì)新表的連接,并且在被連接表中定義了一個(gè)外鍵引用原表的主鍵的情況下經(jīng)常使用。

    <key
    column="columnname"                      (1)
    on-delete="noaction|cascade"             (2)
    property-ref="propertyName"              (3)
    not-null="true|false"                    (4)
    update="true|false"                      (5)
    unique="true|false"                      (6)
    />
    (1)

    column (可選): 外鍵字段的名稱。也可以通過嵌套的 <column>指定。

    (2)

    on-delete (可選, 默認(rèn)是 noaction): 表明外鍵關(guān)聯(lián)是否打開數(shù)據(jù)庫(kù)級(jí)別的級(jí)聯(lián)刪除。

    (3)

    property-ref (可選): 表明外鍵引用的字段不是原表的主鍵(提供給遺留數(shù)據(jù))。

    (4)

    not-null (可選): 表明外鍵的字段不可為空(這意味著無(wú)論何時(shí)外鍵都是主鍵的一部分)。

    (5)

    update (可選): 表明外鍵決不應(yīng)該被更新(這意味著無(wú)論何時(shí)外鍵都是主鍵的一部分)。

    (6)

    unique (可選): 表明外鍵應(yīng)有唯一性約束 (這意味著無(wú)論何時(shí)外鍵都是主鍵的一部分)。

    對(duì)那些看重刪除性能的系統(tǒng),我們推薦所有的鍵都應(yīng)該定義為on-delete="cascade",這樣 Hibernate 將使用數(shù)據(jù)庫(kù)級(jí)的ON CASCADE DELETE約束,而不是多個(gè)DELETE語(yǔ)句。 注意,這個(gè)特性會(huì)繞過 Hibernate 通常對(duì)版本數(shù)據(jù)(versioned data)采用的樂觀鎖策略。

    not-nullupdate 屬性在映射單向一對(duì)多關(guān)聯(lián)的時(shí)候有用。如果你映射一個(gè)單向一對(duì)多關(guān)聯(lián)到非空的(non-nullable)外鍵,你必須<key not-null="true">定義此鍵字段。

    6.1.19. 字段和規(guī)則元素(column and formula elements)

    任何接受column屬性的映射元素都可以選擇接受<column> 子元素。同樣的,formula也可以替換<formula>屬性。

    <column
    name="column_name"
    length="N"
    precision="N"
    scale="N"
    not-null="true|false"
    unique="true|false"
    unique-key="multicolumn_unique_key_name"
    index="index_name"
    sql-type="sql_type_name"
    check="SQL expression"/>
    <formula>SQL expression</formula>

    columnformula 屬性甚至可以在同一個(gè)屬性或關(guān)聯(lián)映射中被合并來(lái)表達(dá),例如,一些奇異的連接條件。

    <many-to-one name="homeAddress" class="Address"
    insert="false" update="false">
    <column name="person_id" not-null="true" length="10"/>
    <formula>'MAILING'</formula>
    </many-to-one>

    6.1.20. 引用(import)

    假設(shè)你的應(yīng)用程序有兩個(gè)同樣名字的持久化類,但是你不想在Hibernate查詢中使用他們的全限定名。除了依賴auto-import="true"以外,類也可以被顯式地“import(引用)”。你甚至可以引用沒有明確被映射的類和接口。

    <import class="java.lang.Object" rename="Universe"/>
    <import
    class="ClassName"              (1)
    rename="ShortName"             (2)
    />
    (1)

    class: 任何Java類的全限定名。

    (2)

    rename (可選 - 默認(rèn)為類的全限定名): 在查詢語(yǔ)句中可以使用的名字。

    6.1.21. any

    這是屬性映射的又一種類型。<any> 映射元素定義了一種從多個(gè)表到類的多態(tài)關(guān)聯(lián)。這種類型的映射常常需要多于一個(gè)字段。第一個(gè)字段持有被關(guān)聯(lián)實(shí)體的類型,其他的字段持有標(biāo)識(shí)符。對(duì)這種類型的關(guān)聯(lián)來(lái)說,不可能指定一個(gè)外鍵約束,所以這當(dāng)然不是映射(多態(tài))關(guān)聯(lián)的通常的方式。你只應(yīng)該在非常特殊的情況下使用它(比如,審計(jì)log,用戶會(huì)話數(shù)據(jù)等等)。

    meta-type 屬性使得應(yīng)用程序能指定一個(gè)將數(shù)據(jù)庫(kù)字段的值映射到持久化類的自定義類型。這個(gè)持久化類包含有用id-type指定的標(biāo)識(shí)符屬性。 你必須指定從meta-type的值到類名的映射。

    <any name="being" id-type="long" meta-type="string">
    <meta-value value="TBL_ANIMAL" class="Animal"/>
    <meta-value value="TBL_HUMAN" class="Human"/>
    <meta-value value="TBL_ALIEN" class="Alien"/>
    <column name="table_name"/>
    <column name="id"/>
    </any>
    <any
    name="propertyName"                      (1)
    id-type="idtypename"                     (2)
    meta-type="metatypename"                 (3)
    cascade="cascade_style"                  (4)
    access="field|property|ClassName"        (5)
    optimistic-lock="true|false"             (6)
    >
    <meta-value ... />
    <meta-value ... />
    .....
    <column .... />
    <column .... />
    .....
    </any>
    (1)

    name: 屬性名

    (2)

    id-type: 標(biāo)識(shí)符類型

    (3)

    meta-type (可選 -默認(rèn)是 string): 允許辨別標(biāo)志(discriminator)映射的任何類型

    (4)

    cascade (可選 -默認(rèn)是none): 級(jí)聯(lián)的類型

    (5)

    access (可選 -默認(rèn)是 property): Hibernate 用來(lái)訪問屬性值的策略。

    (6)

    optimistic-lock (可選 -默認(rèn)是 true): 表明更新此組件是否需要獲取樂觀鎖。換句話說,當(dāng)這個(gè)屬性變臟時(shí),是否增加版本號(hào)(Version)

    6.2. Hibernate 的類型

    6.2.1. 實(shí)體(Entities)和值(values)

    為了理解很多與持久化服務(wù)相關(guān)的Java語(yǔ)言級(jí)對(duì)象的行為,我們需要把它們分為兩類:

    實(shí)體entity 獨(dú)立于任何持有實(shí)體引用的對(duì)象。與通常的Java模型相比,不再被引用的對(duì)象會(huì)被當(dāng)作垃圾收集掉。實(shí)體必須被顯式的保存和刪除(除非保存和刪除是從父實(shí)體向子實(shí)體引發(fā)的級(jí)聯(lián))。這和ODMG模型中關(guān)于對(duì)象通過可觸及保持持久性有一些不同——比較起來(lái)更加接近應(yīng)用程序?qū)ο笸ǔT谝粋€(gè)大系統(tǒng)中的使用方法。實(shí)體支持循環(huán)引用和交叉引用,它們也可以加上版本信息。

    一個(gè)實(shí)體的持久狀態(tài)包含指向其他實(shí)體和類型實(shí)例的引用。值可以是原始類型,集合(不是集合中的對(duì)象),組件或者特定的不可變對(duì)象。與實(shí)體不同,值(特別是集合和組件)是通過可觸及性來(lái)進(jìn)行持久化和刪除的。因?yàn)橹祵?duì)象(和原始類型數(shù)據(jù))是隨著包含他們的實(shí)體而被持久化和刪除的,他們不能被獨(dú)立的加上版本信息。值沒有獨(dú)立的標(biāo)識(shí),所以他們不能被兩個(gè)實(shí)體或者集合共享。

    直到現(xiàn)在,我們都一直使用術(shù)語(yǔ)“持久類”(persistent class)來(lái)代表實(shí)體。我們?nèi)匀粫?huì)這么做。 然而嚴(yán)格說來(lái),不是所有的用戶自定義的,帶有持久化狀態(tài)的類都是實(shí)體。組件就是用戶自定義類,卻是值語(yǔ)義的。java.lang.String類型的java屬性也是值語(yǔ)義的。給了這個(gè)定義以后,我們可以說所有JDK提供的類型(類)都是值類型的語(yǔ)義,而用于自定義類型可能被映射為實(shí)體類型或值類型語(yǔ)義。采用哪種類型的語(yǔ)義取決于開發(fā)人員。在領(lǐng)域模型中,尋找實(shí)體類的一個(gè)好線索是共享引用指向這個(gè)類的單一實(shí)例,而組合或聚合通常被轉(zhuǎn)化為值類型。

    我們會(huì)在本文檔中重復(fù)碰到這兩個(gè)概念。

    挑戰(zhàn)在于將java類型系統(tǒng)(和開發(fā)者定義的實(shí)體和值類型)映射到 SQL/數(shù)據(jù)庫(kù)類型系統(tǒng)。Hibernate提供了連接兩個(gè)系統(tǒng)之間的橋梁:對(duì)于實(shí)體類型,我們使用<class>, <subclass> 等等。對(duì)于值類型,我們使用 <property>, <component> 及其他,通常跟隨著type屬性。這個(gè)屬性的值是Hibernate 的映射類型的名字。Hibernate提供了許多現(xiàn)成的映射(標(biāo)準(zhǔn)的JDK值類型)。你也可以編寫自己的映射類型并實(shí)現(xiàn)自定義的變換策略,隨后我們會(huì)看到這點(diǎn)。

    所有的Hibernate內(nèi)建類型,除了collections以外,都支持空(null)語(yǔ)義。

    6.2.2. 基本值類型

    The built-in basic mapping types may be roughly categorized into 內(nèi)建的 基本映射類型可以大致分為

    integer, long, short, float, double, character, byte, boolean, yes_no, true_false

    這些類型都對(duì)應(yīng)Java的原始類型或者其封裝類,來(lái)符合(特定廠商的)SQL 字段類型。boolean, yes_notrue_false都是Java 中boolean 或者java.lang.Boolean的另外說法。

    string

    java.lang.StringVARCHAR (或者 Oracle的 VARCHAR2)的映射。

    date, time, timestamp

    java.util.Date和其子類到SQL類型DATE, TIMETIMESTAMP (或等價(jià)類型)的映射。

    calendar, calendar_date

    java.util.Calendar 到SQL 類型TIMESTAMPDATE(或等價(jià)類型)的映射。

    big_decimal, big_integer

    java.math.BigDecimaljava.math.BigIntegerNUMERIC (或者 Oracle 的NUMBER類型)的映射。

    locale, timezone, currency

    java.util.Locale, java.util.TimeZonejava.util.CurrencyVARCHAR (或者 Oracle 的VARCHAR2類型)的映射. LocaleCurrency 的實(shí)例被映射為它們的ISO代碼。TimeZone的實(shí)例被影射為它的ID

    class

    java.lang.ClassVARCHAR (或者 Oracle 的VARCHAR2類型)的映射。Class被映射為它的全限定名。

    binary

    把字節(jié)數(shù)組(byte arrays)映射為對(duì)應(yīng)的 SQL二進(jìn)制類型。

    text

    把長(zhǎng)Java字符串映射為SQL的CLOB或者TEXT類型。

    serializable

    把可序列化的Java類型映射到對(duì)應(yīng)的SQL二進(jìn)制類型。你也可以為一個(gè)并非默認(rèn)為基本類型的可序列化Java類或者接口指定Hibernate類型serializable

    clob, blob

    JDBC 類 java.sql.Clobjava.sql.Blob的映射。某些程序可能不適合使用這個(gè)類型,因?yàn)閎lob和clob對(duì)象可能在一個(gè)事務(wù)之外是無(wú)法重用的。(而且, 驅(qū)動(dòng)程序?qū)@種類型的支持充滿著補(bǔ)丁和前后矛盾。)

     

    實(shí)體及其集合的唯一標(biāo)識(shí)可以是除了binaryblobclob之外的任何基礎(chǔ)類型。(聯(lián)合標(biāo)識(shí)也是允許的,后面會(huì)說到。)

    org.hibernate.Hibernate中,定義了基礎(chǔ)類型對(duì)應(yīng)的Type常量。比如,Hibernate.STRING代表string 類型。

    6.2.3. 自定義值類型

    開發(fā)者創(chuàng)建屬于他們自己的值類型也是很容易的。比如說,你可能希望持久化java.lang.BigInteger類型的屬性,持久化成為VARCHAR字段。Hibernate沒有內(nèi)置這樣一種類型。自定義類型能夠映射一個(gè)屬性(或集合元素)到不止一個(gè)數(shù)據(jù)庫(kù)表字段。比如說,你可能有這樣的Java屬性:getName()/setName(),這是java.lang.String類型的,對(duì)應(yīng)的持久化到三個(gè)字段:FIRST_NAME, INITIAL, SURNAME

    要實(shí)現(xiàn)一個(gè)自定義類型,可以實(shí)現(xiàn)org.hibernate.UserTypeorg.hibernate.CompositeUserType中的任一個(gè),并且使用類型的Java全限定類名來(lái)定義屬性。請(qǐng)查看org.hibernate.test.DoubleStringType這個(gè)例子,看看它是怎么做的。

    <property name="twoStrings" type="org.hibernate.test.DoubleStringType">
    <column name="first_string"/>
    <column name="second_string"/>
    </property>

    注意使用<column>標(biāo)簽來(lái)把一個(gè)屬性映射到多個(gè)字段的做法。

    CompositeUserType, EnhancedUserType, UserCollectionType, 和 UserVersionType 接口為更特殊的使用方式提供支持。

    你甚至可以在一個(gè)映射文件中提供參數(shù)給一個(gè)UserType。 為了這樣做,你的UserType必須實(shí)現(xiàn)org.hibernate.usertype.ParameterizedType接口。為了給自定義類型提供參數(shù),你可以在映射文件中使用<type>元素。

    <property name="priority">
    <type name="com.mycompany.usertypes.DefaultValueIntegerType">
    <param name="default">0</param>
    </type>
    </property>

    現(xiàn)在,UserType 可以從傳入的Properties對(duì)象中得到default 參數(shù)的值。

    如果你非常頻繁地使用某一UserType,可以為他定義一個(gè)簡(jiǎn)稱。這可以通過使用 <typedef>元素來(lái)實(shí)現(xiàn)。Typedefs為一自定義類型賦予一個(gè)名稱,并且如果此類型是參數(shù)化的,還可以包含一系列默認(rèn)的參數(shù)值。

    <typedef class="com.mycompany.usertypes.DefaultValueIntegerType" name="default_zero">
    <param name="default">0</param>
    </typedef>
    <property name="priority" type="default_zero"/>

    也可以根據(jù)具體案例通過屬性映射中的類型參數(shù)覆蓋在typedef中提供的參數(shù)。

    盡管 Hibernate 內(nèi)建的豐富的類型和對(duì)組件的支持意味著你可能很少 需要使用自定義類型。不過,為那些在你的應(yīng)用中經(jīng)常出現(xiàn)的(非實(shí)體)類使用自定義類型也是一個(gè)好方法。例如,一個(gè)MonetaryAmount類使用CompositeUserType來(lái)映射是不錯(cuò)的選擇,雖然他可以很容易地被映射成組件。這樣做的動(dòng)機(jī)之一是抽象。使用自定義類型,以后假若你改變表示金額的方法時(shí),它可以保證映射文件不需要修改。

    6.3. SQL中引號(hào)包圍的標(biāo)識(shí)符

    你可通過在映射文檔中使用反向引號(hào)(`)把表名或者字段名包圍起來(lái),以強(qiáng)制Hibernate在生成的SQL中把標(biāo)識(shí)符用引號(hào)包圍起來(lái)。Hibernate會(huì)使用相應(yīng)的SQLDialect(方言)來(lái)使用正確的引號(hào)風(fēng)格(通常是雙引號(hào),但是在SQL Server中是括號(hào),MySQL中是反向引號(hào))。

    <class name="LineItem" table="`Line Item`">
    <id name="id" column="`Item Id`"/><generator class="assigned"/></id>
    <property name="itemNumber" column="`Item #`"/>
    ...
    </class>

    6.4. 其他元數(shù)據(jù)(Metadata)

    XML 并不適用于所有人, 因此有其他定義Hibernate O/R 映射元數(shù)據(jù)(metadata)的方法。

    6.4.1. 使用 XDoclet 標(biāo)記

    很多Hibernate使用者更喜歡使用XDoclet@hibernate.tags將映射信息直接嵌入到源代碼中。我們不會(huì)在本文檔中涉及這個(gè)方法,因?yàn)閲?yán)格說來(lái),這屬于XDoclet的一部分。然而,我們包含了如下使用XDoclet映射的Cat類的例子。

    package eg;
    import java.util.Set;
    import java.util.Date;
    /**
    * @hibernate.class
    *  table="CATS"
    */
    public class Cat {
    private Long id; // identifier
    private Date birthdate;
    private Cat mother;
    private Set kittens
    private Color color;
    private char sex;
    private float weight;
    /*
    * @hibernate.id
    *  generator-class="native"
    *  column="CAT_ID"
    */
    public Long getId() {
    return id;
    }
    private void setId(Long id) {
    this.id=id;
    }
    /**
    * @hibernate.many-to-one
    *  column="PARENT_ID"
    */
    public Cat getMother() {
    return mother;
    }
    void setMother(Cat mother) {
    this.mother = mother;
    }
    /**
    * @hibernate.property
    *  column="BIRTH_DATE"
    */
    public Date getBirthdate() {
    return birthdate;
    }
    void setBirthdate(Date date) {
    birthdate = date;
    }
    /**
    * @hibernate.property
    *  column="WEIGHT"
    */
    public float getWeight() {
    return weight;
    }
    void setWeight(float weight) {
    this.weight = weight;
    }
    /**
    * @hibernate.property
    *  column="COLOR"
    *  not-null="true"
    */
    public Color getColor() {
    return color;
    }
    void setColor(Color color) {
    this.color = color;
    }
    /**
    * @hibernate.set
    *  inverse="true"
    *  order-by="BIRTH_DATE"
    * @hibernate.collection-key
    *  column="PARENT_ID"
    * @hibernate.collection-one-to-many
    */
    public Set getKittens() {
    return kittens;
    }
    void setKittens(Set kittens) {
    this.kittens = kittens;
    }
    // addKitten not needed by Hibernate
    public void addKitten(Cat kitten) {
    kittens.add(kitten);
    }
    /**
    * @hibernate.property
    *  column="SEX"
    *  not-null="true"
    *  update="false"
    */
    public char getSex() {
    return sex;
    }
    void setSex(char sex) {
    this.sex=sex;
    }
    }

    參考Hibernate網(wǎng)站更多的Xdoclet和Hibernate的例子

    6.4.2. 使用 JDK 5.0 的注解(Annotation)

    JDK 5.0 在語(yǔ)言級(jí)別引入了 XDoclet 風(fēng)格的標(biāo)注,并且是類型安全的,在編譯期進(jìn)行檢查。這一機(jī)制比XDoclet的注解更為強(qiáng)大,有更好的工具和IDE支持。例如, IntelliJ IDEA,支持JDK 5.0注解的自動(dòng)完成和語(yǔ)法高亮 。EJB規(guī)范的新修訂版(JSR-220)使用 JDK 5.0的注解作為entity beans的主要元數(shù)據(jù)(metadata)機(jī)制。Hibernate 3 實(shí)現(xiàn)了JSR-220 (the persistence API)的EntityManager,支持通過Hibernate Annotations包定義映射元數(shù)據(jù)。這個(gè)包作為單獨(dú)的部分下載,支持EJB3 (JSR-220)和Hibernate3的元數(shù)據(jù)。

    這是一個(gè)被注解為EJB entity bean 的POJO類的例子

    @Entity(access = AccessType.FIELD)
    public class Customer implements Serializable {
    @Id;
    Long id;
    String firstName;
    String lastName;
    Date birthday;
    @Transient
    Integer age;
    @Dependent
    private Address homeAddress;
    @OneToMany(cascade=CascadeType.ALL,
    targetEntity="Order")
    @JoinColumn(name="CUSTOMER_ID")
    Set orders;
    // Getter/setter and business methods
    }

    注意:對(duì) JDK 5.0 注解 (和 JSR-220)支持的工作仍然在進(jìn)行中,并未完成。

    posted on 2007-04-03 10:16 ???MengChuChen 閱讀(770) 評(píng)論(0)  編輯  收藏 所屬分類: hibernate
    主站蜘蛛池模板: 亚洲Av无码精品色午夜| 国产精品亚洲аv无码播放| 久久精品成人免费国产片小草| 亚洲AV无码成人网站久久精品大| 亚洲高清视频免费| www视频免费看| 亚洲欧洲av综合色无码| 亚洲人成无码网站| 久久精品女人天堂AV免费观看| 亚洲国产精品无码专区| 91情侣在线精品国产免费| 一区二区3区免费视频| 国产亚洲一区二区三区在线| 无码人妻一区二区三区免费| 国产精品视频全国免费观看| 亚洲videosbestsex日本| 亚洲女同成人AⅤ人片在线观看| 看全免费的一级毛片| 亚洲日本中文字幕| 免费少妇a级毛片人成网| 最刺激黄a大片免费网站| 亚洲成AV人影片在线观看| 久久久久亚洲AV无码专区体验| 中国一级特黄高清免费的大片中国一级黄色片 | 成年18网站免费视频网站| 韩国免费A级毛片久久| 亚洲 暴爽 AV人人爽日日碰| 黑人精品videos亚洲人| 国产a级特黄的片子视频免费| 亚洲欧洲日产国码久在线| 亚洲AV乱码一区二区三区林ゆな | 亚洲aⅴ天堂av天堂无码麻豆| 免费a级毛片高清视频不卡| 99久久免费国产特黄| 亚洲欧美综合精品成人导航| 中文字幕亚洲精品资源网| 国产亚洲精品拍拍拍拍拍| 日韩电影免费在线观看视频| 无码精品A∨在线观看免费 | 波多野结衣免费一区视频 | 国产av无码专区亚洲av果冻传媒|