Nhibernate 使用 (一)


一:介紹

       NHibernate 是一個基於.Net 的針對關系型數據庫的對象持久化類庫。Nhibernate 來源於非常優秀的基於Java的Hibernate 關系型持久化工具。
NHibernate 從數據庫底層來持久化你的.Net 對象到關系型數據庫。NHibernate 為你處理這些,遠勝於你不得不寫SQL去從數據庫存取對象。你的代碼僅僅和對象關聯,NHibernat 自動產生SQL語句,並確保對象提交到正確的表和字段中去。

二:ORM

       對象-關系映射(OBJECT/RELATION MAPPING,簡稱ORM),是隨着面向對象的軟件開發方法發展而產生的。面向對象的開發方法是當今企業級應用開發環境中的主流開發方法,關系數據庫是企業級應用環境中永久存放數據的主流數據存儲系統。對象和關系數據是業務實體的兩種表現形式,業務實體在內存中表現為對象,在數據庫中表現為關系數據。內存中的對象之間存在關聯和繼承關系,而在數據庫中,關系數據無法直接表達多對多關聯和繼承關系。因此,對象-關系映射(ORM)系統一般以中間件的形式存在,主要實現程序對象到關系數據庫數據的映射。

三:常用對象

SessionFactory(NHibernate.ISessionFactory) 對屬於單一數據庫的編譯過的映射嗯間的一個線程安全的,不可變的緩存快照。它是Session的工廠,是ConnectioProvider的客戶。可以持有一個可選的(第二級)數據緩存,可以在進程級別或集群級別保存可以在事務中重用的數據。
會話Session(NHibernate.ISession) 單線程,生命期短促的對象,代表應用程序和持久化層之間的一次對話。封裝了一個ADO.NET連接。也是Transaction的工廠。保存有必需的(第一級)持久化對象的緩存,用於遍歷對象圖,或者通過標識符查找對象
持久化對象(Persistent)及其集合(Collection) 生命期短促的單線程對象,包含了持久化狀態和商業功能。它們可能是普通的對象,唯一特別的是他們現在從屬於且僅從屬於一個Session。一旦Session被關閉,他們都將從Session中取消聯系,可以在任何程序層自由使用(比如,直接作為傳送到表現層的DTO,數據傳輸對象)。
臨時對象(Transient Object)及其集合(Collection) 目前沒有從屬於一個Session的持久化類的實例。它們可能是剛剛被程序實例化,還沒來得及被持久化,或者是被一個已經關閉的Session所實例化的。
事務Transaction(NHibernate.ITransaction) (可選)單線程,生命期短促的對象,應用程序用它來表示一批工作的原子操作。是底層的ADO.NET事務的抽象。一個Session某些情況下可能跨越多個Transaction事務。
ConnectionProvider(NHibernate.Connectin.ConnectionProvider) (可選)ADO.NET連接的工廠,從底層的IDbConnection抽象而來。對應用程序不可見,但可以被開發者擴展/實現。
TransactionFactory(net.sf.hibernate.TransactionFactory) (可選)事務實例的工廠,對應用程序不可見,但可以被開發者擴展/實現
ICriteria ICriteria是Expression(表達式)數據加載接口,Expression是一個關系表達式組合,通過它能產生SQL語句的Where部分, 用戶需要通過ISession來間接調用它。
IQuery IQuery是HQL數據加載接口,HQL(Hibernate Query Language)是NHB專用的面向對象的數據查詢語言,它與數據庫的SQL有些類似,但功能更強大!同ICriteria一樣,也需要通過ISession來間接調用它。

 四:栗子

      Nhibernate支持各大主流的數據庫,本文中使用的是mysql數據庫。看Nhibernate的配置文件,文件名 NHibernate.cfg.xml

<?xml version="1.0" encoding="utf-8" ?>
<!-- Add this element -->
<hibernate-configuration  xmlns="urn:nhibernate-configuration-2.2" >
  <session-factory name="NHibernate.Test"><!--命名空間-->
    <!--定制IDriver的類型-->
    <property name="connection.driver_class">NHibernate.Driver.MySqlDataDriver</property>
    <!--用來獲得連接的連接字符串-->
    <property name="connection.connection_string">
      initial catalog=db_test;Data Source=xxx.xxx.x.xx;User Id=test;Password=test;
      pooling=true;min pool size=5; max pool size=100;Connection Timeout=100;
    </property>
    <!--NHibernate方言(Dialect)的類名 - 可以讓NHibernate使用某些特定的數據庫平台的特性-->
    <property name="dialect">NHibernate.Dialect.MySQL5Dialect</property>
    <mapping assembly="NHibernate.Test"/>
  </session-factory>
</hibernate-configuration>
NHibernate方言(Dialect)與數據庫的對應關系
RDBMS 方言
DB2 NHibernate.Dialect.DB2Dialect
PostgreSQL NHibernate.Dialect.PostgreSQLDialect
MySQL NHibernate.Dialect.MySQLDialect
Oracle (any version) NHibernate.Dialect.OracleDialect
Oracle 9/10g NHibernate.Dialect.Oracle9Dialect
Sybase NHibernate.Dialect.SybaseDialect
Microsoft SQL Server 2000 NHibernate.Dialect.MsSql2000Dialect
Microsoft SQL Server 7 NHibernate.Dialect.MsSql7Dialect
Firebird  NHibernate.Dialect.FirebirdDialect

五:數據庫表映射xml,在項目中添加 nhibernate-configuration.xsdnhibernate-mapping.xsd 可以獲得智能提示
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
  <class name="NHibernate.Test.Entity.UserModel, NHibernate.Test"
     table="user"  lazy="false"    discriminator-value="0">
    <id name="Id" column="Id" unsaved-value="0"    type="Int32">
      <generator class="increment" />
    </id>
    <property name="UserName" column="UserName" type="String" length="100"/>
    <property name="Age" column="Age" type="Int32"/>
  </class>
</hibernate-mapping>

     hibernate-mapping 的對應屬性,這個元素包括四個可選的屬性。schema屬性,指明了這個映射所引用的表所在的schema名稱。假若指定了這個屬性,表名會加上所指定的schema的名字擴展schema的名字擴展為全限定名。假若沒有指定,表明就不會使用全限定名。default-cascade指定了未注明cascade屬性和集合類會采用什么樣的默認級聯風格。auto-import屬性默認讓我們在查詢語言中可以使用非全限定名的類名。default-access告訴我們怎么訪問屬性。

<hibernate-mapping
 schema="schemaName" (1)
 default-cascade="none|save-update" 
 auto-import="true|false" default-access="property|field|nosetter|ClassName" 
 assembly="assembly.name" namespace="namespace.name" >
                                                           hibernate-mapping
schema(可選) schemaName 數據庫schema名稱。
default-cascade(可選-默認為none) none|save-update 默認的級聯風格。
auto-import(可選-默認為true) true|false 指定是否我們可以在查詢語言中使用非全限定的類名(僅限於本映射文件中的類)。
default-acess(可選-默認為property) property|field|nosetter|ClassName NHibernate訪問屬性時的策略。
assembly(可選) assembly.name 指定一個程序集,如果在映射文檔中沒有指定程序集,就使用這個程序集
namespace namespace.name 指定一個命名空間前綴,如果在一個映射文檔中沒有指定全限定名,就使用這個命名空間名。

 class:可以使用class元素來定義一個持久化類

  

<class
 name="ClassName" 
 table="tableName"
 discriminator-value="discriminator_value"
 mutable="true|false"
 schema="owner"
 proxy="ProxyInterface"
 dynamic-update="true|false"
 dynamic-insert="true|false"
 polymorphism="implicit|explicit"
 where="arbitrary sql where condition"
 persister="PersisterClass"
 lazy="true|false"
/>
class
name ClassName 持久化類(或者接口)的全限定名
table tableName 對應的數據庫表名。
discriminator-value(可選-默認和類名一樣) discriminator_value 一個用於區分不同的子類的值,在多態行為時使用。
mutable(可選,默認為true) true|false 表明該類的實例可變(不可變)。
schema(可選) owner 覆蓋在根<hibernate-mapping>元素中指定的schema名字
proxy(可選) ProxyInterface 指定一個接口,在延遲裝載時作為代理使用。你可以在這里使用該類自己的名字
dynamic-update(可選,默認為false) true|false 指定用於UPDATE的sql將會在運行時動態生成,並且只更新哪些改變過的字段
dynamic-insert(可選,默認為false) true|false 指定用於INSERT的sql將會在運行時動態生成,並且只包含哪些非空字段
polymorphism(可選,默認為implicit(隱式)) implicit|explicit 界定是隱式還是顯式的使用查詢多態。
where(可選) arbitrary sql where condition 指定一個附加的SQL WHERE 條件,在抓取這個類的對象時會一直增加這個條件
persister(可選) PersisterClass 指定一個定制的IClassPersister。
lazy(可選) true|false 假若設置lazy=“true”,就是設置這個類自己的名字作為proxy接口的一種等價快捷方式

主鍵Id

<id 
 name="propertyName" 
 type="typename" 
 column="column_name" 
 unsaved-value="any|none|null|id_value" 
 access="field|property|nosetter|ClassName"> <generator class="generatorClass"/>
</id>
Id
name(可選)
propertyName 標識屬性的名字。
type(可選)
typename 標識NHibernate類型的名字。
unsaved-value(可選-默認為null) any|none|null|id_value 一個特定的標識屬性值,用來標識該實例是剛剛創建的,尚未保存。這可以把這種實例和從以前的sssion中裝載過(可能又做過修改)但未再次持久化的實例區分開來。
column(可選-默認為屬性名) column_name 主鍵字段的名字
access(可選-默認為property) field|property|nosetter|ClassName NHibernate用來訪問屬性值的策略

如果name屬性不存在,會認為這個類沒有標識屬性。

unsaved-value屬性很重要!如果你的類的標識屬性不是默認為null的,你應該指定正確的默認值。特別重要的是在使用值類型System.ValueType,例如System.Int32或者System.Guid作為你的<id>屬性時確保清楚的設置這個屬性,因為System.ValueType對象不可能為null值。

還有一個另外的<composite-id>聲明可以訪問舊式的多主鍵數據。不鼓勵使用這種方式。

gennerator 

<id name="Id" type="Int64" column="uid" unsaved-value="0">
  <generator class="NHibernate.Id.TableHiLoGenerator">
  <param name="table">uid_table</param>
  <param name="column">next_hi_value_column</param>
  </generator>
</id>

 必須聲明的<generator>子元素是一個.NET類的名字,用來為該持久化類的屬性生成唯一的標識。如果這個生成器實例需要某些配置值或者初始化參數,用<param>元素傳遞。

identity

 

對DB2,MySQL, MS SQL Server, Sybase和HypersonicSQL的內置標識字段提供支持。返回的標識符是 Int64, Int32 或者 Int16類型的。

sequence(序列)

對DB2,MySQL, PostgreSQL, Oracle的內置標識字段提供支持。返回的標識符是Int64 Int32 或者 Int16類型的。

hilo(高低位)

使用一個高/低位算法來高效的生成Int64, Int32 或者 Int16類型的標識符。給定一個表和字段(默認分別是hibernate_unique_key 和next)作為高位值得來源。高/低位算法生成的標識符只在一個特定的數據庫中是唯一的。

seqhilo(使用序列的高低位)

使用一個高/低位算法來高效的生成Int64, Int32 或者 Int16類型的標識符,給定一個數據庫序列(sequence)的名字。

uuid.hex

 

用一個System.Guid和它的ToString(string format)方法生成字符串類型的標識符。字符串的長度取決於 format的配置。

uuid.string

用一個新的System.Guid產生一個byte[] ,把它轉換成字符串。

guid

用一個新的System.Guid 作為標識符。

guid.comb

用Jimmy Nilsson在文章http://www.informit.com/articles/article.asp?p=25862中描述的算法產生一個新的System.Guid。

native(本地)

根據底層數據庫的能力選擇 identity, sequence 或者 hilo中的一個。

assigned(程序設置)

讓應用程序在save()之前為對象分配一個標示符。

foreign(外部引用)

使用另外一個相關聯的對象的標識符。和<one-to-one>聯合一起使用。

聯合ID(composite-id)

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

如果表使用聯合主鍵,你可以把類的多個屬性組合成為標識符屬性。<composite-id>元素接受<key-property>屬性映射和<key-many-to-one>屬性映射作為子元素。

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

你的持久化類必須重載Equals()和HashCode()方法,來實現組合的標識符判斷等價.也必須實現Serializable接口

不幸的是,這種組合關鍵字的方法意味着一個持久化類是它自己的標識。除了對象自己之外,沒有什么方便的“把手”可用。你必須自己初始化持久化類的實例,在使用組合關鍵字Load()持久化狀態之前,必須填充他的聯合屬性。我們會在TODO: LINKTOCOMPENENTS 中說明一種更加方便的方法,把聯合標識實現為一個獨立的類,下面描述的屬性只對這種備用方法有效:

 
        

name (可選)

一個組件類型,持有聯合標識

class (可選 - 默認為通過反射(reflection)得到的屬性類型)

 作為聯合標識的組件類名。

unsaved-value (可選 - 默認為 none)

 假如被設置為any的值,就表示新創建,尚未被持久化的實例將持有的值。

識別器(discriminator)

 <discriminator
  column="discriminator_column"
  type="discriminator_type"
  force="true|false"
  insert="true|false" />

column (可選 - 默為    class)

 識別器字段的名字

type (可選 - 默認為 String)

 一個NHibernate字段類型的名字

force (可選 - 默認為 false)

 強制"NHibernate指定允許的識別器值,就算取得的所有實例都是根類的。

insert (可選 - 默認為 true)

 當識別器是被映射的組件的標識符的一部分時設置為false。

標識器字段的實際值是根據<class> 和<subclass>元素的discriminator-value得來的。

文章來源:http://www.cnblogs.com/wolf-sun/p/4138918.html






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM