一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

NHibernate Step by Step

 mefly 2007-12-28
lisirui





級別: 新手上路
精華: 0
發(fā)帖: 12
威望: 13 點
金錢: 120 RMB
注冊時間:2007-09-01
查看作者資料 發(fā)送短消息 發(fā)送郵件 推薦此帖 引用回復這個帖子



NHibernate Step by Step (一) Hello,NHibernate!

好了,今天我們正式開始NHibernate的歷程,在第一次的練習中,我將盡量詳細地講解環(huán)境的配置,以后將不再詳細解釋。

基本的軟件環(huán)境如下:
1.NHibernate
www. 當前版本是1.0.2
2.Code Smith
http://www./
3.NHibernate模板 點擊這里下載
當然,少不了VS2005跟SQLServer了,我這里用的是SQLServer2005,教程用在SQLServer2000上應該沒有問題,默認情況下,我將建立并使用一個叫NHibernate的數(shù)據(jù)庫。

首先,我們先建立一個最簡單的Person表,如下完整腳本(你可以進行修改以適合自己的數(shù)據(jù)庫):

CODE:

USE [NHibernate]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Person](
  [id] [int] IDENTITY(1,1) NOT NULL,
  [name] [varchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED
(
  [id] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF



僅有兩個字段,一個自動增長的id,一個name,如下:


然后將下載的nhibernate-template解壓,打開Code Smith,將模板加入”Template Explorer”,如下:


然后在其中的NHibernate.cst上點右鍵,選擇“Execute”,彈出設置窗口,在左邊的屬性窗口進行如下設置:


注意:SourceDatabase屬性在第一次選擇時需要配置一個連接字符串,配置好后Code Smith將記錄下來。 Assembly屬性代表的是生成文件的默認Assembly名,而NameSpace,顧名思義,就是使用的命名空間了,這里我們全部使用”Test.Model”,請記住這個名字,點擊左下角的Generate,將會在指定的輸出目錄下產生兩個文件:Person.cs,Person.hbm.xml。

好了,NHibernate需要的類文件和映射文件生成完了,我們可以開始干活了?。ㄉ蒒Hibernate文件均是如此步驟,以后不再贅述)

新建立一個類庫工程,為了簡潔起見,我們命名為Model,需要注意的是,為了跟剛才生成的文件對應,我們需要在Model工程的屬性頁中將起Assembly名字設為上面的“Test.Model”,如下:



然后將剛才生成的兩個文件Person.cs和Person.hbm.xml加入到Model工程中來,選中Person.hbm.xml文件,在屬性窗口中將其“Build Action”設置為“Embedded Resource”(這是非常重要的一步,否則NHibernate將無法找到映射文件),如下:


build,ok,通過。

然后建立一個控制臺工程,命名為Console1,添加NHibernate和上面Model項目的引用,另外添加一個應用程序配置文件,如下:
CODE:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
  <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System,
            Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>

<nhibernate>
  <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />
  <add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
  <add key="hibernate.connection.connection_string" value="Server=localhost;Initial Catalog=NHibernate;Integrated Security=SSPI" />
  <add key="hibernate.connection.isolation" value="ReadCommitted"/>
  <add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" />
</nhibernate>

</configuration>


然后編寫如下代碼:
CODE:

using System;
using System.Collections.Generic;
using System.Text;
using NHibernate;
using NHibernate.Cfg;
using Test.Model;

namespace Console1
{
  class Program
  {
    static void Main(string[] args)
    {
        Configuration config = new Configuration().AddAssembly("Test.Model");
        ISessionFactory factory = config.BuildSessionFactory();
        ISession session = factory.OpenSession();

        Person person = new Person();
        person.Name = "Jackie Chan";

        ITransaction trans = session.BeginTransaction();
        try
        {
          session.Save(person);
          trans.Commit();
          Console.WriteLine("Insert Success!");
        }
        catch (Exception ex)
        {
          trans.Rollback();
          Console.WriteLine(ex.Message);
        }
    }
  }
}


運行,ok,執(zhí)行成功!!
我們到數(shù)據(jù)庫檢查一下,如下:


我們想要添加的記錄已經(jīng)成功加入到數(shù)據(jù)庫中??!
是不是感覺有些神奇啊?好,我們開始詳細解釋。
先來看生成的兩個文件,第一個是Person.cs,如下:
CODE:
using System;
using System.Collections;

namespace Test.Model
{
  Person#region Person

  /**//// <summary>
  /// Person object for NHibernate mapped table 'Person'.
  /// </summary>
  public class Person
  {
    Member Variables#region Member Variables
   
    protected int _id;
    protected string _name;

    #endregion

    Constructors#region Constructors

    public Person() { }

    public Person( string name )
    {
        this._name = name;
    }

    #endregion

    Public Properties#region Public Properties

    public int Id
    {
        get {return _id;}
        set {_id = value;}
    }

    public string Name
    {
        get { return _name; }
        set
        {
          if ( value != null && value.Length > 50)
            throw new ArgumentOutOfRangeException("Invalid value for Name", value, value.ToString());
          _name = value;
        }
    }

   

    #endregion
  }
  #endregion
}



你可以發(fā)現(xiàn),這完全是一個普通的poco類(Plain Old CLR Object),僅僅是對數(shù)據(jù)庫person表的一個完全映射,不依賴于任何框架,可以用來作為持久化類,你可以在任何地方使用而不用擔心依賴于某些神秘的運行時東西。

另外,NHibernate需要知道怎樣去加載(load)和存儲(store)持久化類的對象。這正是NHibernate映射文件發(fā)揮作用的地方。映射文件告訴NHibernate它應該訪問數(shù)據(jù)庫(database)里面的哪個表(table)及應該使用表里面的哪些字段(column),這就是我們今天要講的重點了,Person.hbm.xml,如下:
CODE:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="Test.Model.Person, Test.Model" table="Person">
<id name="Id" type="Int32" unsaved-value="0">
  <column name="id" sql-type="int" not-null="true" unique="true" index="PK_Person"/>
  <generator class="native" />
</id>
<property name="Name" type="String">
  <column name="name" length="50" sql-type="varchar" not-null="true"/>
</property>
</class>
</hibernate-mapping>


不用說,最頂層的hibernate-mapping節(jié)點是NHibernate用來進行映射的根了,其中,包含一個class節(jié)點,里面的name屬性對應我們的Person類,注意,需要完整的限定名;而table屬性,則顯而易見是對應數(shù)據(jù)庫中的Person表了。
我們再往里面看,分別有兩個節(jié)點,一個是id,對應數(shù)據(jù)庫中的id,一個是屬性name,對應表中的column name和Person類中的name屬性,整個映射文件簡捷明了,一看即知。實際上這是由代碼產生工具產生的映射文件,里面很多東西我們其實可以省略,如下寫法:
<property name=”Name” column=”name” />
NHibernate將自動去匹配數(shù)據(jù)庫中的列而不需要我們來設置。

下面,我們來看一下應用程序配置文件中都記錄了那些東西,如下:
hibernate.connection.provider_class
定制IConnectionProvider的類型.
例如:full.classname.of.ConnectionProvider (如果提供者創(chuàng)建在NHibernate中), 或者 full.classname.of.ConnectionProvider, assembly (如果使用一個自定義的IConnectionProvider接口的實現(xiàn),它不屬于NHibernate)。

hibernate.connection.driver_class
定制IDriver的類型.
full.classname.of.Driver (如果驅動類創(chuàng)建在NHibernate中), 或者 full.classname.of.Driver, assembly (如果使用一個自定義IDriver接口的實現(xiàn),它不屬于NHibernate)。

hibernate.connection.connection_string
用來獲得連接的連接字符串.

hibernate.connection.isolation
設置事務隔離級別. 請檢查 System.Data.IsolationLevel 來得到取值的具體意義并且查看數(shù)據(jù)庫文檔以確保級別是被支持的。
例如: Chaos, ReadCommitted, ReadUncommitted, RepeatableRead, Serializable, Unspecified

hibernate.dialect
NHibernate方言(Dialect)的類名 - 可以讓NHibernate使用某些特定的數(shù)據(jù)庫平臺的特性
例如: full.classname.of.Dialect(如果方言創(chuàng)建在NHibernate中), 或者full.classname.of.Dialect, assembly (如果使用一個自定義的方言的實現(xiàn),它不屬于NHibernate)。

接著,我們開始解釋代碼的執(zhí)行,如下:
CODE:
Configuration config = new Configuration().AddAssembly("Test.Model");

//通過配置對象來產生一個SessionFactory對象,這是一個Session工廠,
//那么Session是用來干什么的呢?一個Session就是由NHibernate封裝
//的工作單元,我們可以近似地認為它起到ADO.Net中Connection的作用。
ISessionFactory factory = config.BuildSessionFactory();
ISession session = factory.OpenSession();

Person person = new Person();
person.Name = "Jackie Chan";

//這里,開啟一個由NHibernate封裝的事務,當然,在這里最終代表
//的還是一個真實的數(shù)據(jù)庫事務,但是我們已經(jīng)不需要再區(qū)分到底是
//一個SqlTransaction還是一個ODBCTransaction了
ITransaction trans = session.BeginTransaction();
try
{
  //保存,提交,就這么簡單!!
      session.Save(person);
    trans.Commit();
    Console.WriteLine("Insert Success!");
}
catch (Exception ex)
{
    trans.Rollback();
    Console.WriteLine(ex.Message);
}


現(xiàn)在有了一個基本的概念了吧??
好了,第一篇就講這么多,我們下次再接著練習。

Step by Step,顧名思義,是一步一步來的意思,整個教程我將貫徹這一理念,待此系列結束后,我們再就某些高級話題進行深入。
任何建議或者批評,請e:abluedog@163.com

[1 樓] Posted:2007-09-01 17:05| 頂端
lisirui





級別: 新手上路
精華: 0
發(fā)帖: 12
威望: 13 點
金錢: 120 RMB
注冊時間:2007-09-01
查看作者資料 發(fā)送短消息 發(fā)送郵件 推薦此帖 引用回復這個帖子



NHibernate Step by Step(二) 單表操作

接著第一期,我們繼續(xù)。

為了方便學習測試,從今天開始我將使用MS Test來進行測試,這樣就避免了在一個Console工程里不停地添加、注釋代碼了。



提示:為了在VS2005IDE中獲得NHibernate配置文件的代碼提示,請將你的$NHibernate\src\NHibernate下的nhibernate-configuration-2.0.xsd、nhibernate-mapping-2.0.xsd拷貝到\Program Files\Microsoft Visual Studio 8\Xml\Schemas下,這樣當你編輯配置文件或者映射文件時,你將得到完整的代碼提示。
VS2003請拷貝到\Program Files\Microsoft Visual Studio .NET 2003\Common7\Packages\schemas\xml下。


NHibernat內部使用log4net來進行日志操作,今天我們將在配置文件中添加log4net的配置,這樣我們在測試的時候將可以清楚地看到NHibernate是如何進行工作的。

應用配置文件修改如下:

CODE:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
  <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System,Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>

<nhibernate>
  <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />
  <add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
  <add key="hibernate.connection.connection_string" value="Server=localhost;Initial Catalog=NHibernate;Integrated Security=SSPI" />
  <add key="hibernate.connection.isolation" value="ReadCommitted"/>
  <add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" />
  <add key="show_sql" value="true" />
</nhibernate>

<log4net>
  <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
    <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
    </layout>
  </appender>
  <root>
    <level value="ALL" />
    <appender-ref ref="ConsoleAppender" />
  </root>

</log4net>

</configuration>


請注意添加:
CODE:
<add key="show_sql" value="true" />



關于log4net的使用,我們這里不做詳細的講解,有興趣的請參考如下地址:

http://logging./log4net/



接著,我們在上次的工程組中添加一個名為Test1的測試項目,將其中的不需要的手動測試去掉。請注意:除了NHibernate\Model引用外,還需要添加如下3個引用:

log4net,System.Data,System.Xml.



修改代碼如下:
CODE:
using System;
using System.Text;
using System.Collections;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NHibernate;
using NHibernate.Cfg;
using log4net;
using log4net.Config;
using Test.Model;

namespace Test1
{
  /**//// <summary>
  /// Summary description for UnitTest1
  /// </summary>
  [TestClass]
  public class UnitTest1
  {
    static ISessionFactory factory;
    static ILog logger;
    ISession session;

    public UnitTest1()
    {
    }

    Additional test attributes#region Additional test attributes
   
      [ClassInitialize()]
      public static void MyClassInitialize(TestContext testContext)
      {
        XmlConfigurator.Configure();
        logger = LogManager.GetLogger(typeof(Test1.UnitTest1));
        Configuration config = new Configuration().AddAssembly("Test.Model");
        factory = config.BuildSessionFactory();
      }
   
      [ClassCleanup()]
      public static void MyClassCleanup() { }
   
      [TestInitialize()]
      public void MyTestInitialize()
      {
        session = factory.OpenSession();
      }
   
      [TestCleanup()]
      public void MyTestCleanup()
      {
        session.Close();
      }
   
    #endregion
  }
}


我們在測試的開始對Configuration\SessionFactory\Log進行初始化。在每一個Test的開始獲取一個新的session,每一個Test結束后即關閉session。



添加如下一個Get測試:
CODE:
[TestMethod]
public void TestRead()
{
    Person person = (Person)session.Get(typeof(Person), 1);
    Assert.IsTrue(person.Name == "Jackie Chan");
}


我們在前面曾經(jīng)插入一條名為“Jackie Chan”的記錄,現(xiàn)在在Test Manager中選中TestRead,運行,ok,Passed!
我們使用了session.Get來獲取記錄,方法如下:

object Get(Type clazz,object id);

很簡單,一目了然。



我們切換到Test Results窗口,雙擊測試成功的TestRead方法,這時將會有一個詳細的測試結果顯示出來,NHibernate將使用我們指定的log4net來輸出詳細信息,我們仔細觀察:
CODE:
2006-04-15 13:52:13,000 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - opened session

2006-04-15 13:52:13,015 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - loading [Person#1]

2006-04-15 13:52:13,015 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - attempting to resolve [Person#1]

2006-04-15 13:52:13,015 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - object not resolved in any cache [Test.Model.Person#1]

2006-04-15 13:52:13,015 [AdpaterExeMgrThread1] DEBUG NHibernate.Persister.EntityPersister [(null)] - Materializing entity: Test.Model.Person#1



2006-04-15 13:52:13,078 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.BatcherImpl [(null)] - Opened new IDbCommand, open IDbCommands :1

2006-04-15 13:52:13,078 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.BatcherImpl [(null)] - Building an IDbCommand object for the SqlString: SELECT person0_.id as id0_, person0_.name as name0_ FROM Person person0_ WHERE person0_.id=:id

2006-04-15 13:52:13,093 [AdpaterExeMgrThread1] DEBUG NHibernate.Type.Int32Type [(null)] - binding '1' to parameter: 0

2006-04-15 13:52:13,093 [AdpaterExeMgrThread1] INFO NHibernate.Loader.Loader [(null)] - SELECT person0_.id as id0_, person0_.name as name0_ FROM Person person0_ WHERE person0_.id=@p0

2006-04-15 13:52:13,093 [AdpaterExeMgrThread1] DEBUG NHibernate.SQL [(null)] - SELECT person0_.id as id0_, person0_.name as name0_ FROM Person person0_ WHERE person0_.id=@p0

2006-04-15 13:52:13,093 [AdpaterExeMgrThread1] DEBUG NHibernate.SQL [(null)] - @p0 = '1'



2006-04-15 13:52:13,093 [AdpaterExeMgrThread1] DEBUG NHibernate.Connection.DriverConnectionProvider [(null)] - Obtaining IDbConnection from Driver

2006-04-15 13:52:13,859 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.BatcherImpl [(null)] - Opened Reader, open Readers :1

2006-04-15 13:52:13,859 [AdpaterExeMgrThread1] DEBUG NHibernate.Loader.Loader [(null)] - processing result set

2006-04-15 13:52:13,875 [AdpaterExeMgrThread1] DEBUG NHibernate.Loader.Loader [(null)] - result row: 1

2006-04-15 13:52:13,875 [AdpaterExeMgrThread1] DEBUG NHibernate.Loader.Loader [(null)] - Initializing object from DataReader: 1

2006-04-15 13:52:13,875 [AdpaterExeMgrThread1] DEBUG NHibernate.Loader.Loader [(null)] - Hydrating entity: Test.Model.Person#1

2006-04-15 13:52:13,906 [AdpaterExeMgrThread1] DEBUG NHibernate.Type.StringType [(null)] - returning 'Jackie Chan' as column: name0_

2006-04-15 13:52:13,906 [AdpaterExeMgrThread1] DEBUG NHibernate.Loader.Loader [(null)] - done processing result set (1 rows)

2006-04-15 13:52:13,937 [AdpaterExeMgrThread1] DEBUG NHibernate.Driver.NHybridDataReader [(null)] - running NHybridDataReader.Dispose()

2006-04-15 13:52:13,937 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.BatcherImpl [(null)] - Closed Reader, open Readers :0

2006-04-15 13:52:13,937 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.BatcherImpl [(null)] - Closed IDbCommand, open IDbCommands :0

2006-04-15 13:52:13,937 [AdpaterExeMgrThread1] DEBUG NHibernate.Loader.Loader [(null)] - total objects hydrated: 1

2006-04-15 13:52:13,953 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - resolving associations for: [Test.Model.Person#1]

2006-04-15 13:52:13,953 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - done materializing entity [Test.Model.Person#1]

2006-04-15 13:52:13,953 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - initializing non-lazy collections

2006-04-15 13:52:13,953 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - closing session

2006-04-15 13:52:13,953 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - disconnecting session

2006-04-15 13:52:13,953 [AdpaterExeMgrThread1] DEBUG NHibernate.Connection.ConnectionProvider [(null)] - Closing connection

2006-04-15 13:52:13,968 [AdpaterExeMgrThread1] DEBUG NHibernate.Impl.SessionImpl [(null)] - transaction completion



在其中,我們可以發(fā)現(xiàn):

CODE:
2006-04-15 13:52:13,093 [AdpaterExeMgrThread1] DEBUG NHibernate.SQL [(null)] - SELECT person0_.id as id0_, person0_.name as name0_ FROM Person person0_ WHERE person0_.id=@p0

2006-04-15 13:52:13,093 [AdpaterExeMgrThread1] DEBUG NHibernate.SQL [(null)] - @p0 = '1'




對了,就是這里,NHibernate替我們構造了一條sql語句,并添加一個參數(shù),然后將我們在代碼中賦的id值1來填充,這樣,一條完整的可以執(zhí)行的sql語句產生了。

請注意:在產生sql語句的前面,NHibernate構造了一個IDBCommand,然后在sql語句產生完全后,獲取連接,通過一個DataReader來填充Persion對象給我們使用,這就是NHibernate替我們做的事,是不是很簡單???(真的很簡單嗎??看看源代碼吧!?。?br>
請仔細研究輸出的日志。



如法炮制,我們添加另外3個Test,完成單個表的全部CRUD操作,如下完整代碼:
CODE:
[TestMethod]

    public void TestCreate()

    {

        Person person = new Person();

        person.Name = "Jackie Chan";



        ITransaction trans = session.BeginTransaction();

        try

        {

          session.Save(person);

          trans.Commit();

          Assert.IsTrue(person.Id > 0);

        }

        catch (Exception ex)

        {

          trans.Rollback();

          Assert.Fail(ex.Message);

        }

    }



    [TestMethod]

    public void TestUpdate()

    {

        Person person = (Person)session.Get(typeof(Person), 1);

        person.Name = "Jet Li";



        ITransaction trans = session.BeginTransaction();

        try

        {

          session.Save(person);

          trans.Commit();

          Assert.IsTrue(person.Name == "Jet Li");

        }

        catch (Exception ex)

        {

          trans.Rollback();

          Assert.Fail(ex.Message);

        }

    }



    [TestMethod]

    public void TestRead()

    {

        Person person = (Person)session.Get(typeof(Person), 1);

        Assert.IsTrue(person.Name == "Jackie Chan");

    }



    [TestMethod]

    public void TestDelete()

    {

        Person person = (Person)session.Get(typeof(Person), 1);



        ITransaction trans = session.BeginTransaction();

        try

        {

          session.Delete(person);

          trans.Commit();

        }

        catch (Exception ex)

        {

          trans.Rollback();

          Assert.Fail(ex.Message);

        }

    }



Delete的方法如下:

void Delete(object obj);

直接傳入需要delete的對象即可。



好了,基本的操作都完成了,是不是很Easy?
好了,這一篇就講這么多,我們下次再接著練習。


Step by Step,顧名思義,是一步一步來的意思,整個教程我將貫徹這一理念。

任何建議或者批評,請e:abluedog@163.com

[2 樓] Posted:2007-09-01 17:08| 頂端
lisirui





級別: 新手上路
精華: 0
發(fā)帖: 12
威望: 13 點
金錢: 120 RMB
注冊時間:2007-09-01
查看作者資料 發(fā)送短消息 發(fā)送郵件 推薦此帖 引用回復這個帖子



NHibernate Step by Step (三) Configuration和Sessionfactory

好了,我們再從頭看一看Configuration,是否只能從App.config中取配置信息??

當然不是了,以下是3種最常見的配置:

<1> Configuration config = new Configuration();

這種配置方法將會到應用程序配置文件(App.Config,Web.Config)中查找NHibernate的配置信息,NHibernate的配置節(jié)必須符合應用程序配置文件個格式,前面的教程我們已經(jīng)看到過了。

<2> Configuration config = new Configuration().Configure();

    這種配置方法將會在應用的相同目錄查找名為”hibernate.cfg.xml”的標準Hibernate配置

    文件,格式如下:

CODE:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.0" >

    <session-factory name="MySessionFactory">

        <!-- properties -->
        <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
        <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
        <property name="connection.connection_string">Server=localhost;initial catalog=Hibernate;Integrated Security=SSPI</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 files -->
        <mapping assembly="Test.Model" />
    </session-factory>
</hibernate-configuration>


    <3> Configuration config = new Configuration().Configure(configFileName);

    這種配置方法將查找指定的Hibernate標準配置文件,可以是絕對路徑或者相對路徑。

    另外我們還可以通過編碼的方式添加配置信息:

 
CODE:
 

Hashtable props = new Hashtable();
props[“dialect”] = xxxx;



config.Properties = props;



    這種方式不夠配置文件來的靈活,所以我們一般不建議使用。



在取得config后,我們還需要進行映射文件添加,同樣,我們常用以下3種不同的方法:

CODE:

<1> config.AddXmlFile(“Person.hbm.xml”);

<2> config.AddClass(typeof(Test.Model.Person));

<3> config.AddAssembly(“Test.Model”);



以上方法都可以用“階梯式“的編碼風格,如下:
 
CODE:

config.AddXmlFile(“Person.hbm.xml”)

    .AddXmlFile(“User.hbm.xml”)

    .AddClass(typeof(Test.Model.Customer));




當然,為了方便起見,我們一般把所有的影射類文件及xml文件統(tǒng)一放在一個程序集中,然后使用config.AddAssembly(assemblyName)的方式,讓NHibernate自動去查找指定程序集中所有的映射文件和映射類。

你有沒有發(fā)現(xiàn)在我們使用標準的hibernate配置文件時,有如下一個元素:

<!-- mapping files -->

<mapping assembly="Test.Model" />

對了,你想的不錯,我們可以避免在代碼中捆綁映射程序集,而在配置文件中指定,這種方式可以說是最靈活的了。

提示:在Web程序中,最好將配置文件改為config的后綴,否則在沒有添加對xml的asp.net映射的情況下,你的配置文件就有可能被下載喲??!



我們再來看看Sessionfactory:

CODE:


ISessionFactory sessionFactory = config.BuildSessionFactory();


在由Configuration構造完SessionFactory后,SessionFactory便保留了配置信息而不再需要Configuration,之后Configurationd的任何變化都不會影響到已經(jīng)創(chuàng)建好的SessionFactory,如果你的配置信息發(fā)生變化,那么,毋庸置疑,你必須重新由Configuration構造出一個新的SessionFactory來。

注意:SessionFactory是一個Heavy Object,它不但保存了配置信息,而且還有所有的映射關系(你可以調用GetAllCollectionMetadata方法試驗一下),以及需要進行總體維護的緩存等等信息,所以,我們不應該重復地創(chuàng)建SessionFactory對象,而應該充分共用已經(jīng)創(chuàng)建出來的SessionFactory對象,同時,SessionFactory也是一個線程安全的對象,所以在多線程的場景下也完全可以共用。在我們實際開發(fā)中,我們可以在初始化的部分構造一個SessionFactory即可,比如,在一個公共靜態(tài)類中初始化一個SessionFactory的readonly常量等等。



另外需要注意的是,如果你要對多個數(shù)據(jù)庫進行操作,那么你可以配置針對每個數(shù)據(jù)庫而創(chuàng)建對應的SessionFactory——大部分情況下,一個數(shù)據(jù)庫對應一個SessionFactory足夠使用。



好了,這一篇就講這么多,我們下次再接著練習。
任何建議或者批評,請e:abluedog@163.com

[3 樓] Posted:2007-09-01 17:11| 頂端
lisirui





級別: 新手上路
精華: 0
發(fā)帖: 12
威望: 13 點
金錢: 120 RMB
注冊時間:2007-09-01
查看作者資料 發(fā)送短消息 發(fā)送郵件 推薦此帖 引用回復這個帖子



NHibernate Step by Step (四)Session、Query及HQL




我們總結一下在第二篇中的Session操作:

1. 獲取記錄


CODE:

Person person = (Person)session.Get(typeof(Person),1);


2. 保存記錄
CODE:

session.Save(person);


3. 刪除記錄

CODE:

Person person = (Person)session.Get(typeof(Person),1);

session.Delet(person);




我們再來看看其它幾種方式:

1. Load

CODE:

Person person = (Person)session.Load(typeof(Person),1);


是不是感覺和Get一樣?其實……很不一樣!

Get在找不到對象時會返回一個null引用,而Load則會拋出一個ObjectNotFoundException,所以,不應該用Load來判斷記錄是否存在。另外還有兩條非常重要的區(qū)別,我們將放在高級話題討論。

2. Query

CODE:

IList list = session.CreateQuery(“from Person”).List();

Person person = (Person)list[0];


    ~!#@^?? from Person??#$@*&^$

    這是蝦米??

    好象有點象SQL,不過少了個select??!而且也沒有表名啊!

    這就是久負盛名的HQL——Hibernate Query Language!

    HQL實際上是基于對象查詢的一種仿SQL腳本,在運行期間,Hibernate會自動根據(jù)映射關系將之轉換為真正的SQL語句來執(zhí)行。

    什么?又一種SQL?不是說使用O/R Mapping就可以不寫SQL了嗎,怎么又多了一種“SQL”??

    當然不是這樣了,之所以產生HQL,就是為了能夠更加靈活更加面向對象地操作數(shù)據(jù),而且你不應該把HQL當成一種新的SQL,因
  為它——太簡單好學了!

    看看下面的HQL,是不是很熟悉??

CODE:
   

select p.Name from Person as p where p.Id=1
select Name from Person where Age>20
select Id,Name from Person where Id>1 and Age>20




    認出來老兄弟了吧?。?br>
    (從這里開始,我們給person表添加了一個age列,請注意)

    ok,我們這里就詳細解釋。

    “from Person ”意思是取出Person類映射的person表中的所有記錄,對應的SQL是:

    “Select * from person”

    還可以加上別名:from Person (as) p = Select * from person (as) p

    這樣一解釋就很清楚了吧!一句話,你便已經(jīng)掌握了HQL的50%!

    而“select Name from Person”,當然也就是只取person表的name列了!

    你所知道的where中的and、or、is、like、between、>、<、=等等都可以直接拿來使用,

    如下:

CODE:
 

select p.Name from Person p where p.Age>20

from Person p where p.Age between 20 and 30

from person p where p.Age in (20,30)

from person p where p.Name is null

from person p where p.Name like “Jaki%”
 
 

    注意:字段大小寫應該盡量跟屬性名稱保持一致,尤其是在使用別名的情況下,如:

    p.age將會導致一個“無法解析屬性age“的錯誤。但是在不使用別名的情況下我的機器上”age“和’Age“一樣可以通過,雖然如此,
  建議還是跟類文件保持一致。



執(zhí)行HQL是通過IQuery來實現(xiàn)的,如下是詳細的寫法:

CODE:

IQuery query = session.CreateQuery(“from Person”);

IList list = query.List();



  通過session來創(chuàng)建一個query,然后執(zhí)行query的List方法,返回符合條件的IList。

如上面的“from Person“,將返回person表的所有記錄,list中將包含映射到Person類

的對應表中所有記錄的對象。



好了,這一篇就講這么多,我們下次再接著練習。
任何建議或者批評,請e:abluedog@163.com

[4 樓] Posted:2007-09-01 17:13| 頂端
lisirui





級別: 新手上路
精華: 0
發(fā)帖: 12
威望: 13 點
金錢: 120 RMB
注冊時間:2007-09-01
查看作者資料 發(fā)送短消息 發(fā)送郵件 推薦此帖 引用回復這個帖子



NHibernate Step by Step (五)Criteria Query

可能很多人象我一樣,剛開始接觸HQL時,腦袋一片混沌,這是什么語法嘛?。≈赃@樣,是因為我們總是會先入為主地將之與SQL想比,雖然HQL看起來很SQL,而且設計時就有這樣的意圖,但是畢竟是兩種差別很大的東西,難免就會出現(xiàn)理解偏差的問題。好了,我們今天就不讓大家腦袋發(fā)暈了,HQL我們暫時放一放。今天我們來說另外一種查詢方法:

CODE:

Criteria Query.


什么是Criteria Query?簡單說,就是將我們的查詢條件封裝為一個預定義的查詢對象,由這個查詢對象來執(zhí)行查詢,而不用我們再去寫HQL了,而且更接近我們貫常的編程習慣。

是不是很不錯?讓我們來look look:

CODE:

//創(chuàng)建關聯(lián)到某個類的查詢對象
ICriteria criteria = session.CreateCriteria(typeof(Person));

//添加表達式
criteria.Add(Expression.Eq("Name","Jackie Chan"));

IList list = criteria.List();



注意這一句:

CODE:

Expression.Eq("Name","Jackie Chan")


Eq是Equal的縮寫,意思是添加一個查詢表達式,Person.Name = “Jackie Chan”

對應HQL就是:
CODE:

from Person p where p.Name=”Jackie Chan”


NHibernate會在運行時動態(tài)生成類似上面的HQL,我們可以在配置文件把show-sql打開,觀看生成的SQL。

這樣是不是感覺清晰多了?又回到我們以前的編碼習慣了!


為了對應HQL的種種查詢條件,NHibernate預定義了大量的Expression方法,我們列幾個如下:

CODE:

Eq       = Equal
Gt       = Greater than
Lt       = Less than
Like     = Like
Not       = Not
IsNull     = Is Null

基本上對應了大部分HQL的語義,詳細的說明請參考api。


下面,我們詳細介紹Criteria的用法。

1. Example查詢


我們常常有這樣的查詢頁面:

用戶可以輸入“姓名”、“性別”、“年齡”等等來進行查詢,而我們常常的做法就是如下的煩瑣:

CODE:

string condition = “”;
if(txtName.Text != null)
    condition += “ Name=” + txtName.Text;

if(txtSex.Text != null)
    condition += “ and Sex=” + txtSex.Text;

……



代碼看起來實在是不甚美觀,有什么解決辦法呢?

Criteria提供了專為這種問題而設計的Example查詢,如下:

CODE:


ICriteria criteria = session.CreateCriteria(typeof(Person));

Person person = new Person();
person.Name = "Jackie Chan";
person.Age = 50;

//創(chuàng)建一個Example對象
criteria.Add(Example.Create(person));
IList list = criteria.List();


請注意:

CODE:

criteria.Add(Example.Create(person));


這句代碼的意思是通過構造的person對象的屬性來生成表達式,實際生成的代碼如下:


CODE:

SELECT this.id as id0_, this.name as name0_, this.age as age0_ FROM Person this WHERE (this.age = @p0)


對應上面的問題,我們簡單地new出一個person對象,然后填充其屬性即可,不用再去構造那丑陋的條件判斷語句了!


2. 排序

我們想對返回的list進行排序,該怎么辦呢?如下:

CODE:

ICriteria criteria = session.CreateCriteria(typeof(Person));
criteria.Add(Expression.Gt("Age", 20));

//添加一個排序對象
criteria.AddOrder(Order.Asc("Age"));

IList list = criteria.List();




請注意:

CODE:


criteria.AddOrder(Order.Asc("Age"));


這句代碼的意思是在criteria上構造一個排序對象,并以Age屬性做正序排列,NHibernate在運行時會生成如下語句:

CODE:


SELECT this.id as id0_, this.name as name0_, this.age as age0_ FROM Person this WHERE this.age > @p0 ORDER BY this.age asc


如你所猜想,Order類肯定有另外一個“Desc“方法:)


3. 限制記錄范圍

在顯示大量的記錄時,我們常常采用的方法就是分頁,如果用NHibernate來做,該怎么辦呢?

如下代碼:

CODE:

ICriteria criteria = session.CreateCriteria(typeof(Person));

//從第10條記錄開始取
criteria.SetFirstResult(10);

//取20條記錄
criteria.SetMaxResults(20);

IList list = criteria.List();


這樣,我們就達到了分頁的目的。

注意:

NHibernate的分頁機制實際上依賴于不同的數(shù)據(jù)庫實現(xiàn),所以,對特定的某種數(shù)據(jù)庫,并不一定是效率最好的,比如對SQLServer(為什么受傷的總是俺?為什么總是說俺比不上Oracle?俺都趕在2005年年底出2005版本了?。。?。想知道為什么嗎?很簡單,check一下上面代碼生成的SQL就清楚了!或者深入點再看看NHibernate的分頁代碼,我就不解釋了,自己動手,豐衣足食:)


總體來講,Criteria對我們來說更熟悉,更容易上手,但是目前Criteria還是不夠完善——將對應的HQL一一封裝實在太煩瑣了,所以NHibernate還是以HQL查詢?yōu)橹鳎覀冊谑褂玫臅r候則看需要了,要么使用HQL,要么HQL和Criteria混合使用,重要的是解決問題,對不?


好了,這一篇就講這么多,我們下次再接著練習。
任何建議或者批評,請e:abluedog@163.com

[5 樓] Posted:2007-09-01 17:16| 頂端
 

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    在线观看日韩欧美综合黄片| 国产av熟女一区二区三区蜜桃| 国产欧美一区二区另类精品| 国产视频福利一区二区| 欧美亚洲三级视频在线观看| 欧美日韩在线第一页日韩| 91日韩在线视频观看| 亚洲人午夜精品射精日韩| 日本在线高清精品人妻| 国产激情国产精品久久源| 黄色国产一区二区三区| 不卡中文字幕在线免费看| 欧美日韩校园春色激情偷拍| 日韩一级一片内射视频4k| 亚洲熟女精品一区二区成人| 亚洲综合色婷婷七月丁香| 成人欧美一区二区三区视频| 久久精品国产99精品最新| 日韩精品一区二区亚洲| 国产午夜精品福利免费不| 九九热在线免费在线观看| 欧美日韩一区二区午夜| 中文字幕久热精品视频在线 | 亚洲国产精品久久琪琪| 欧美一区二区三区视频区| 亚洲中文字幕熟女丝袜久久| 亚洲欧美日本国产有色| 亚洲av在线视频一区| 好吊日成人免费视频公开| 日韩高清毛片免费观看| 久久免费精品拍拍一区二区| 在线免费观看黄色美女| 99久久国产亚洲综合精品| 亚洲视频一级二级三级| 一级欧美一级欧美在线播| 熟女一区二区三区国产| 国产又粗又深又猛又爽又黄| 欧美黄色黑人一区二区| 九九热在线视频精品免费| 国产高清一区二区白浆| 欧美午夜色视频国产精品|