Hello NHibernate
创建一个非常简单的NHibernate的应用,它类似于一个留言簿的功能,可以将用户输入的信息保存到数据库中。
准备工作
首先从SourceForge上下载NHibernate最新版,本文基于NHibernate 2.0。将下载的压缩包解压缩到一个目录下。然后,启动VS.Net Studio,创建一个Windows应用程序的项目,起名为HelloNHibernate,首先把nhibernate-mapping.xsd、nhibernate-configuration.xsd两个文件添加到项目中,也可添加到C:\Program Files\Microsoft Visual Studio 8\Xml\Schemas目录下,然后添加NHibernate.dll, log4jnet.dll, Iesi.Collections.dll, Castle.DynamicProxy2.dll引用(位于NHibernate的Bin子目录下)。
接下来,创建一个在MS Sql Server2000上创建一个NHibernate的数据库。有了数据库,我们需要写app.config(web项目为web.config)或hibernate.cfg.xml配置文件告诉NHibernate到什么地方去找数据库,两种方法都可以,它们的配置分别为(此设置在表现层):
(1)app.config或web.config配置文件内容:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider, NHibernate</property>
<!-- This is the System.Data.dll provider for MSSQL Server -->
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string">
Data Source=.;Initial Catalog=NHibernate;Persist Security Info=True;User ID=sa;Password=123456
</property>
<property name="show_sql">true</property>
<property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property>
<mapping assembly="HelloNHibernate"/>
</session-factory>
</hibernate-configuration>
<appSettings/>
<connectionStrings>
</connectionStrings>
<system.web>
</system.web>
</configuration>
(2) hibernate.cfg.xml配置文件内容(使用是需把此文件属性Copy to Output directory改为Copy if newer或Always Copy):
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider, NHibernate</property>
<!-- This is the System.Data.dll provider for MSSQL Server -->
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string">
Data Source=.;Initial Catalog=NHibernate;Persist Security Info=True;User ID=sa;Password=123456
</property>
<property name="show_sql">true</property>
<property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property>
<mapping assembly="HelloNHibernate"/>
</session-factory>
</hibernate-configuration>
配置文件中的参数具有下面的含义:
参数 |
值 |
hibernate.show_sql |
True表示向控制台输出运行中产生的Sql,用于调试目的 |
hibernate.connection.provider |
表示使用指定的类来提供数据库连接缓冲池。 |
hibernate.dialect |
表示NHibernate方言的类名,可以让NHibernate使用某些特定数据库平台的特性,目前NHibernate支持Sql Server, Oracle, Mysql, Firebird, Sybase, PostgreSql等数据库方言。 |
hibernate.connection.driver_class |
Ado.Net的驱动类,支持SqlServer, Oracle, Mysql,OleDb, ODBC,Firebird等驱动。 |
hibernate.connection.connection_string |
对应于Ado.Net的连接串。 |
业务域模型
根据需求,我们首先来设计业务域模型,模型非常简单,只有两个属性,其中Id唯一标识一个类的实例,相当于类的主键,Text表示用户输入的信息,示意图如下:
根据业务域模型,创建对应的.Net类的定义,代码如下:
public class Message
{
private int _id;
public virtual int Id
{
get { return _id; }
set { _id = value; }
}
private string _Text;
public virtual string Text
{
get { return _Text; }
set { _Text = value; }
}
public Message()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
public override string ToString()
{
return _Text;
}
}
Message类除了定义了必需的两个属性外,还重载了基类的ToString方法,这是为了便于在界面中进行显示。有了类定义,我们还需要创建存储Message对象的数据库表,下面就是同Message对象一一对应的数据库表Messages的DbSchema脚本:
CREATE TABLE [dbo].[messages] (
[MsgId] [int] IDENTITY (1, 1) NOT NULL ,
[Text] [varchar] (200) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]
GO
接下来,我们要编写OR Mapping 映射的配置文件Message.hbm.xml来指定Message对象同数据库表的映射关系,下面是创建的映射文件内容:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="HelloNHibernate.Message, HelloNHibernate" table="messages">
<id name="Id" column="MsgId" type="Int32">
<generator class="identity" />
</id>
<property name="Text" type="String" length="200"/>
</class>
</hibernate-mapping>
Xml文件中的Class元素的name属性指定了要进行映射的类的名称为HelloNHibernate.Message,同时这个类需要从HelloNHibernate assembly中进行加载, table属性指定了Message类在数据库中进行持久存储的库表名称为messages。而Id元素用于声明类标识属性对应于数据库表的主键字段的映射关系,其中name属性标识类的标识属性名称,column属性标识messages表的主键字段的名称,type是标识字段的数据类型,而内嵌的generator元素则指明主键字段唯一值的生成方法,这里identity表示NHibernate使用Sql Server数据库本身提供的自增加字段的特性来保证键值唯一。如果我们想自己给Id属性赋值来保证唯一性的话,可以设定class属性为assigned,这样NHibernate将不会自动生成键值。
定义完文件之后,别忘了在VS.Net Studio中将Message.hbm.xml的生成操作属性修改为嵌入的资源。还要注意的是,如果每次大家修改了hbm.xml文件,一定要使用“重新生成”命令来编译项目,否则VS.Net不会重新编译整个项目。
表现层设计
表现层的界面设计非常简单,在界面上放置一个ListBox用于显示消息列表,一个TextBox用于输入消息,三个Button分别用于查询消息列表、添加消息和删除消息:
(1)查询消息列表
在系统每次加载时,我们需要获取信息列表,下面就是加载信息列表的代码:
private void HelloForm_Load(object sender, System.EventArgs e)
{
QueryMessages();
}
private ISessionFactory factory;
private void QueryMessages()
{
//查询信息列表
Configuration cfg = new Configuration().Configure();
//cfg.AddAssembly("HelloNHibernate");
//Configure()方法是首先检查App.config文件(web项目里为web.config文件)是否含有NHibernate配置信息,如果无则检查hibernate.cfg.xml文件
//AddAssembly()方式在配置文件里没有<mapping assembly="HelloNHibernate"/>时使用
factory = cfg.BuildSessionFactory();
ISession session = factory.OpenSession();
IList messages = session.CreateCriteria(typeof(Message)).List();
this.lbMsg.Items.Clear();
foreach(Message msg in messages)
this.lbMsg.Items.Add(msg);
session.Close();
}
在QueryMessages方法中,我们首先创建一个Configuration类,然后调用AddAssembly方法利用反射方法将装配件中定义的所有以.hbm.xml命名的Mapping文件加载到系统中,而BuildSessionFactory方法则利用app.config和hbm.xml配置文件中的定义创建一个SessionFactory,然后用SessionFactory工厂类创建一个Session会话类,通过调用会话类的条件查询方法CreateCriteria返回所有类型为 Message的对象列表。最后,边历列表将消息对象添加到列表框中,并关闭Session,释放ADO.Net的连接对象。
(2)添加消息
添加消息稍微有一些不同的是,每次添加时我们都启动一个事务,保证添加消息操作的原子性,代码如下:
private void btnAdd_Click(object sender, System.EventArgs e)
{
//添加消息
if (this.tbMsg.Text.Trim()==String.Empty)
{
MessageBox.Show("消息输入框不能为空!");
return;
}
Message msg=new Message();
msg.Text=this.tbMsg.Text.Trim();
Configuration cfg = new Configuration().Configure();
//cfg.AddAssembly("HelloNHibernate");
//Configure()方法是首先检查App.config文件(web项目里为web.config文件)是否含有NHibernate配置信息,如果无则检查hibernate.cfg.xml文件
//AddAssembly()方式在配置文件里没有<mapping assembly="HelloNHibernate"/>时使用
factory = cfg.BuildSessionFactory();
ISession session=factory.OpenSession();
ITransaction transaction = session.BeginTransaction();
session.Save(msg);
transaction.Commit();
session.Close();
this.lbMsg.Items.Add(msg);
}
运行后,添加几条记录,用Sql Server可以察看到数据库中的数据示意入下:
(3)删除消息
删除消息的操作同添加比较类似,代码示意如下:
private void btnDel_Click(object sender, System.EventArgs e)
{
//删除消息
if (this.lbMsg.SelectedIndex==-1)
{
MessageBox.Show("请选中要删除的消息!");
return;
}
Message msg=(Message)lbMsg.Items[lbMsg.SelectedIndex];
Configuration cfg = new Configuration().Configure();
//cfg.AddAssembly("HelloNHibernate");
//Configure()方法是首先检查App.config文件(web项目里为web.config文件)是否含有NHibernate配置信息,如果无则检查hibernate.cfg.xml文件
//AddAssembly()方式在配置文件里没有<mapping assembly="HelloNHibernate"/>时使用
factory = cfg.BuildSessionFactory();
ISession session=factory.OpenSession();
ITransaction transaction = session.BeginTransaction();
session.Delete(msg);
transaction.Commit();
session.Close();
this.lbMsg.Items.RemoveAt(lbMsg.SelectedIndex);
}
完成上面的程序后,大家会发现整个过程中我们没有写一条Sql语句就完成了添加、删除、查询数据的功能,所有的Sql语句都由NHibernate在后台为我们完成了,要想察看NHibernate生成的Sql语句的话,我们可以启动Sql Server的事件探查器来监视程序运行过程中的Sql。