NHibernate快速起步
NHibernate快速起步
注:本文中使用的是NH1.0.2版本,其他版本配置可能略有不同。
示例代碼下載。
數據庫腳本下載
一、體系結構
首先我們來看看NHibernate的體系結構:
NHibernate是數據庫和應用程序之間的持久化層,應用程序和NHibernate通過持久化(Persistent)對象聯系在一起。NHibernate使用app.config或者web.config和映射文件進行設置。
下面來看看怎么使用NHibernate API的一個最小子集。
下面是圖中一些對象的定義:
Configuration(NHibernate.Cfg.Configuration)
Session的工廠。
代表應用程序和持久化層之間的一次對話。封裝了一個ADO.NET連接。也是Transaction的工廠。保存有必需的(第一級)持久化對象的緩存,用于遍歷對象圖,或者通過標識符查找對象。
(可選) 單線程,生命期短促的對象,應用程序用它來表示一批工作的原子操作。是底層的ADO.NET事務的抽象。一個Session某些情況下可能跨越多個Transaction 事務。
?
二、示例代碼
我們看看他們是如何協同工作的,請看下面的代碼。
代碼示例(未改變數據庫中的數據,查詢操作):
//配置Configuration Configuration?cfg?=?new?Configuration().Configure(); //創建ISessionFactory ISessionFactory?factory?=?cfg.BuildSessionFactory(); //打開ISession ISession?session?=?factory.OpenSession(); try { ????在這里添加操作 } finally { ????session.Close(); }Configuration的Configure方法,將使用應用程序的配置文件或者hibernate.cfg.xml文件的<hibernate-configuration>節點進行配置,返回值是一個配置好了的Configuration對象的實例。
然后這個Configuration通過BuildSessionFactory方法創建ISessionFactory的實例。
ISessionFactory的實例通過OpenSession打開一個ISession的實例,用這個實例完成數據庫的操作,然后關閉它。
如果你的代碼中需要事務,只需要把代碼稍微修改一下。
代碼示例(改變了數據庫中的數據,數據的增刪改):
//配置Configuration Configuration?cfg?=?new?Configuration().Configure(); //創建ISessionFactory ISessionFactory?factory?=?cfg.BuildSessionFactory(); //定義事務 ITransaction?tx?=?null; //打開ISession ISession?session?=?factory.OpenSession(); try { ????//開始事務 ????tx?=?session.BeginTransaction(); ????在這里添加操作 ????tx.Commit(); } catch(HibernateException?ex) { ????if?(tx!=null)?tx.Rollback(); ????throw?ex; } finally { ????//關閉ISession ????session.Close(); }我一般在不影響數據的方法(例如:查詢)中不包含事務,而影響數據的方法(例如:增刪改)使用事務。
?
三、配置文件
前面提到Configuration的Configure方法需要用到應用程序的配置文件或者hibernate.cfg.xml文件,這里我使用hibernate.cfg.xml配置文件,在下一章我們再探討使用應用程序的配置文件和其他的配置方法。
這是一個典型的配置文件:
<?xml?version="1.0"?encoding="utf-8"??> <hibernate-configuration?xmlns="urn:nhibernate-configuration-2.0"> ????<session-factory?name="DDLLY.MyDoc.NHibernateTest.QuickStart"> ????????<!--?屬性?--> ????????<property?name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property> ????????<property?name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property> ????????<property?name="connection.connection_string">server=.;database=user;uid=sa;pwd=App1234;</property> ????????<property?name="show_sql">false</property> ????????<property?name="dialect">NHibernate.Dialect.MsSql2000Dialect</property> ????????<property?name="use_outer_join">true</property> ????????<property?name="query.substitutions">true?1,?false?0,?yes?'Y',?no?'N'</property> ????????<!--?映射文件?--> ????????<mapping?assembly="DDLLY.MyDoc.NHibernateTest.QuickStart"?/> ????</session-factory> </hibernate-configuration>屬性connection.provider設置了數據庫連接提供者(一般不需要更改,除非你決定自己實現提供者)。
connection.driver_class設置了數據庫的的驅動類(這里設置了SqlServer的驅動類)。
connection.connection_string是數據庫的連接字符串。
show_sql設置是否在運行時是否在控制臺顯示正在執行的SQL語句(這個屬性在調試程序時很有用)。
dialect是NHibernate方言, 可以讓NHibernate使用某些特定的數據庫平臺的特性。
use_outer_join在后面的章節會有介紹。
query.substitutions,把NHibernate查詢中的一些短語替換為SQL短語(比如說短語可能是函數或者字符)。
mapping節點設置了將使用到的映射文件,現在的設置方法是使用"DDLLY.MyDoc.NHibernate.QuickStart“中所有的映射文件。
?
四、映射文件
ISession怎么知道和數據庫的哪張表哪個字段打交道,以及怎么把表和實體對象聯系起來呢?靠的就是映射文件。
假設我們有個很簡單的例子,我們有如下的一張表需要進行數據操作(字段和表含義一看就知道,我就不羅嗦了):
CREATE TABLE [dbo].[users] ( [Id] [int] IDENTITY (1, 1) NOT NULL , [UserName] [nvarchar] (64) NOT NULL , [Password] [varchar] (32) NOT NULL , [Email] [varchar] (64) NULL )我們設置它的映射文件和相應的代碼文件:
<?xml?version="1.0"?encoding="utf-8"??>? <hibernate-mapping?xmlns="urn:nhibernate-mapping-2.0"> ????<class?name="DDLLY.MyDoc.NHibernateTest.QuickStart.User,?DDLLY.MyDoc.NHibernateTest.QuickStart"?table="users"> ????????<id?name="Id"?type="Int32"> ????????????<generator?class="identity"?/> ????????</id> ???????? ????????<property?name="UserName"?type="String"/> ????????<property?name="Password"?type="String"/> ????????<property?name="Email"?type="String"/> ????</class>???? </hibernate-mapping> ?namespace?DDLLY.MyDoc.NHibernateTest.QuickStart { ????/**////?<summary> ????///?User實體 ????///?</summary> ????public?class?User ????{ ????????public?User() ????????{ ????????} ????????private?int?m_Id; ????????private?string?m_UserName; ????????private?string?m_Password; ????????private?string?m_Email; ????????public?int?Id ????????{ ????????????get?{?return?m_Id;?} ????????????set?{?m_Id?=?value;?} ????????} ????????public?string?UserName ????????{ ????????????get?{?return?m_UserName;?} ????????????set?{?m_UserName?=?value;?} ????????} ????????public?string?Password ????????{ ????????????get?{?return?m_Password;?} ????????????set?{?m_Password?=?value;?} ????????} ????????public?string?Email ????????{ ????????????get?{?return?m_Email;?} ????????????set?{?m_Email?=?value;?} ????????} ????} }<class name="DDLLY.MyDoc.NHibernate.QuickStart.User, DDLLY.MyDoc.NHibernate.QuickStart" table="users"> 表示映射文件對應的類文件是DDLLY.MyDoc.NHibernate.QuickStart程序集中的 DDLLY.MyDoc.NHibernate.QuickStart.User類,逗號后面是表示程序集。對應的數據庫表為users。
<id name="Id" type="Int32">
<generator class="identity" />
</id>
表示Id是主鍵字段,generator是生成器,這里是使用SqlServer中內置標識字段來生成。
property定義了其他的字段。
?
五、完成代碼
好了,下面我們可以開始對數據進行操作了。
我們來看看ISession為我們提供的常用方法。
Load:讀取實體對象
Find:通過HQL查找實體對象
Save:保存實體對象
Delete:刪除實體對象
用這些方法我們便可以完成對數據庫的增刪改查的操作了。下面是我完成的代碼(使用NUnit進行測試)。
using?System.Collections; using?System.Data.SqlClient; using?NHibernate; using?NHibernate.Cfg; using?NUnit.Framework; namespace?DDLLY.MyDoc.NHibernateTest.QuickStart { ????/**////?<summary> ????///?User測試類 ????///?</summary> ????[TestFixture] ????public?class?UserFixture ????{ ????????常量#region?常量 ????????/**////?<summary> ????????///?連接字符串 ????????///?</summary> ????????private?const?string?CONNECTIONSTRING?=?"server=.;database=user;uid=sa;pwd=App1234;"; ????????#endregion ????????SetUp和TearDown#region?SetUp和TearDown ????????[SetUp] ????????public?void?SetUp() ????????{ ????????????//添加名為LLY,密碼為123456的用戶,因為這是數據庫的第一條記錄,所以數據庫標識為1 ????????????string?SetUpSql?=?"INSERT?INTO?users([UserName],[Password])?VALUES('LLY','123456')"; ????????????SqlExecuteNonQuery(SetUpSql); ????????} ????????[TearDown] ????????public?void?TearDown() ????????{ ????????????//清空users表,并把標識(identity)清零 ????????????string?TearDownSql?=?"TRUNCATE?TABLE?users"; ????????????SqlExecuteNonQuery(TearDownSql); ????????} ????????#endregion ????????私有方法#region?私有方法 ????????/**////?<summary> ????????///?執行SQL語句 ????????///?</summary> ????????///?<param?name="sql">SQL語句</param> ????????private?void?SqlExecuteNonQuery(string?sql) ????????{ ????????????SqlConnection?con?=?new?SqlConnection(CONNECTIONSTRING); ????????????con.Open(); ????????????SqlCommand?cmd?=?new?SqlCommand(); ????????????cmd.Connection?=?con; ????????????cmd.CommandText?=?sql; ????????????cmd.ExecuteNonQuery(); ????????????con.Close(); ????????} ????????#endregion ????????測試方法#region?測試方法 ????????/**////?<summary> ????????///?測試讀取用戶 ????????///?</summary> ????????[Test] ????????public?void?TestLoadUser() ????????{ ????????????User?user; ????????????//配置Configuration ????????????Configuration?cfg?=?new?Configuration().Configure(); ????????????//創建ISessionFactory ????????????ISessionFactory?factory?=?cfg.BuildSessionFactory(); ????????????//打開ISession ????????????ISession?session?=?factory.OpenSession(); ????????????try ????????????{ ????????????????user?=?session.Load(typeof?(User),?1)?as?User; ????????????} ????????????finally ????????????{ ????????????????session.Close(); ????????????} ????????????//************************數據檢查***************************** ????????????//檢查 ????????????Assert.IsNotNull(user,?"沒有找到ID為1的用戶!"); ????????????Assert.AreEqual("LLY",?user.UserName,?"沒有找到名字為LLY的用戶!"); ????????} ????????/**////?<summary> ????????///?測試查找用戶 ????????///?</summary> ????????[Test] ????????public?void?TestFindUser() ????????{ ????????????IList?userlist; ????????????//配置Configuration ????????????Configuration?cfg?=?new?Configuration().Configure(); ????????????//創建ISessionFactory ????????????ISessionFactory?factory?=?cfg.BuildSessionFactory(); ????????????//打開ISession ????????????string?hql?=?"from?User?as?u?where?u.UserName='LLY'"; ????????????ISession?session?=?factory.OpenSession(); ????????????try ????????????{ ????????????????userlist?=?session.Find(hql); ????????????} ????????????finally ????????????{ ????????????????session.Close(); ????????????} ????????????//************************數據檢查***************************** ????????????//檢查 ????????????Assert.AreEqual(1,?userlist.Count,?"名字為LLY的用戶個數不為1!"); ????????} ????????/**////?<summary> ????????///?測試添加用戶 ????????///?</summary> ????????[Test] ????????public?void?TestAddUser() ????????{ ????????????User?newUser?=?new?User(); ????????????//配置Configuration ????????????Configuration?cfg?=?new?Configuration().Configure(); ????????????//創建ISessionFactory ????????????ISessionFactory?factory?=?cfg.BuildSessionFactory(); ????????????//定義事務 ????????????ITransaction?tx?=?null; ????????????//打開ISession ????????????ISession?session?=?factory.OpenSession(); ????????????try ????????????{ ????????????????//開始事務 ????????????????tx?=?session.BeginTransaction(); ????????????????newUser.UserName?=?"DDL"; ????????????????newUser.Password?=?"123456"; ????????????????newUser.Email?=?"DDLLY@tom.com"; ????????????????//?保存新用戶 ????????????????session.Save(newUser); ????????????????tx.Commit(); ????????????} ????????????catch?(HibernateException?ex) ????????????{ ????????????????if?(tx?!=?null)?tx.Rollback(); ????????????????throw?ex; ????????????} ????????????finally ????????????{ ????????????????//關閉ISession ????????????????session.Close(); ????????????} ????????????//************************數據檢查***************************** ????????????IList?userlist; ????????????string?hql?=?"from?User?as?u?where?u.UserName='DDL'"; ????????????session?=?factory.OpenSession(); ????????????try ????????????{ ????????????????userlist?=?session.Find(hql); ????????????} ????????????finally ????????????{ ????????????????session.Close(); ????????????} ????????????//檢查是否有且僅有一個名稱為DDL的用戶 ????????????Assert.AreEqual(1,?userlist.Count,?"名字為DDL的用戶個數不為1!"); ????????} ????????/**////?<summary> ????????///?測試刪除用戶 ????????///?</summary> ????????[Test] ????????public?void?TestDeleteUser() ????????{ ????????????IList?userlist; ????????????User?user; ????????????//配置Configuration ????????????Configuration?cfg?=?new?Configuration().Configure(); ????????????//創建ISessionFactory ????????????ISessionFactory?factory?=?cfg.BuildSessionFactory(); ????????????//定義事務 ????????????ITransaction?tx?=?null; ????????????//打開ISession ????????????ISession?session?=?factory.OpenSession(); ????????????try ????????????{ ????????????????//開始事務 ????????????????tx?=?session.BeginTransaction(); ????????????????user?=?session.Load(typeof?(User),?1)?as?User; ????????????????session.Delete(user); ????????????????tx.Commit(); ????????????} ????????????catch?(HibernateException?ex) ????????????{ ????????????????if?(tx?!=?null)?tx.Rollback(); ????????????????throw?ex; ????????????} ????????????finally ????????????{ ????????????????session.Close(); ????????????} ????????????//************************數據檢查***************************** ????????????string?hql?=?"from?User?as?u?where?u.UserName='LLY'"; ????????????session?=?factory.OpenSession(); ????????????try ????????????{ ????????????????userlist?=?session.Find(hql); ????????????} ????????????finally ????????????{ ????????????????session.Close(); ????????????} ????????????//檢查 ????????????Assert.AreEqual(0,?userlist.Count,?"名字為LLY的用戶沒有被刪除!"); ????????} ????????/**////?<summary> ????????///?測試更新用戶 ????????///?</summary> ????????[Test] ????????public?void?TestUpdateUser() ????????{ ????????????User?user; ????????????//配置Configuration ????????????Configuration?cfg?=?new?Configuration().Configure(); ????????????//創建ISessionFactory ????????????ISessionFactory?factory?=?cfg.BuildSessionFactory(); ????????????//定義事務 ????????????ITransaction?tx?=?null; ????????????//打開ISession ????????????ISession?session?=?factory.OpenSession(); ????????????try ????????????{ ????????????????//開始事務 ????????????????tx?=?session.BeginTransaction(); ????????????????user?=?session.Load(typeof?(User),?1)?as?User; ????????????????user.Password?=?"123"; ????????????????session.Update(user); ????????????????tx.Commit(); ????????????} ????????????catch?(HibernateException?ex) ????????????{ ????????????????if?(tx?!=?null)?tx.Rollback(); ????????????????throw?ex; ????????????} ????????????finally ????????????{ ????????????????session.Close(); ????????????} ????????????//************************數據檢查***************************** ????????????session?=?factory.OpenSession(); ????????????try ????????????{ ????????????????user?=?session.Load(typeof?(User),?1)?as?User; ????????????} ????????????finally ????????????{ ????????????????session.Close(); ????????????} ????????????//檢查 ????????????Assert.IsNotNull(user,?"沒有找到名字為LLY的用戶!"); ????????????Assert.AreEqual("123",?user.Password,?"沒有找到名字為LLY的用戶!"); ????????} ????????#endregion ????} }總結
以上是生活随笔為你收集整理的NHibernate快速起步的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】牛人杰作 管饭哥登场
- 下一篇: 谈谈网站设计时图片的使用