运用Nhibernate进行对象/关系数据库映射需要进行几个步骤,首先建立数据表,然后建立与表对应的类,然后再创建关于类与数据表的映射关系文件,最后配置Nhibernate的配置文件以便连接到对应的数据库。整个映射过程就算是完毕了,这样就可以通过对象来对数据库中的数据就系操作了。不过由于是第一次使用Nhibernate,从创建第一个demo到编译成功到运行完毕中间也遇到了不少的问题,足足花掉了我一个下午的时间。为了让想要学习Nhibernate的朋友少走点弯路,我也总结了这次经验,在这里跟大家分享一下,下面就那我今天创建的这个Project来逐一解说。
在创建Project之前我们应该选择适合我们使用的Nhibernate来进行开发。本人就是因为版本的问题折腾了很多时间,而且在编译时是没有问题的,但在运行的时候就出错了。所以选择合适的版本很重要。目前Nhibernate最新版本是3.0.0 beta1。但此版本需要.net3.5的支持,如果是.net2.0版本的项目运行时就会抛出异常,提示无法找到System.Core库。然后Nhibernate 2.1.0GA和2.1.1GA需要.net2.0 sp1支持。不然也是会抛出异常。由于本人用的是VS2005 .net2.0所以只能使用2.0.1GA这个版本。把他下载下来(文件名为:NHibernate-2.0.1.GA-bin)解压后里面有两个文件夹和三个文件,如下图:主要用到的是bin中的类库,至于nhibernate-configuration.xsd和nhibernate-mapping.xsd分别是Nhibernate的配置文件和映射文件的Schema,这两个文件可以拷贝到你的VS安装目录下的XML/Schema目录下,这样当用VS写配置和映射文件时就会进行有效性检查了。
好了,接下来就开始建立数据表。我在这里建立一个叫user的数据表,表中只有两个字段,分别是id和name,其结构如下图所示:
数据表建立好后就开始建立Project,看到网上很多教程里面都新建类库项目来使用Nhibernate,然后通过Nunit来测试类库。为了方便演示我就不这么做了,我直接创建WindowFrom项目叫做NhibernateDemo,然后直接添加一个按钮来进行测试。首先需要编写一个User类来对象数据库的字段。这个类的内容如下:
using System;
using System.Collections.Generic;
using System.Text;
namespace NHibernateDemo
{
public class User
{
private int id;
private string name;
public int ID
{
get
{
return id;
}
set
{
id = value;
}
}
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
}
}
这个类对应了数据库中的两个字段,接下来就要写映射文件,映射文件的命名方式要符合XXX.hbm.xml,所以需要建立一个User.hbm.xml的文件,其内容如下:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
<class name="NHibernateDemo.User, NHibernateDemo" table="user" >
<id name="ID" column="id" unsaved-value="0">
<generator class="assigned" />
</id>
<property name="Name" column="name" length="50" not-null="true"></property>
</class>
</hibernate-mapping>
以上的映射文件中的标签所表示意思以及作用经过我在网上找到的一些资料对其进行整理,
class标签用来定义一个持久化类。
name:持久化类(或者接口)的全限定名 "," 程序集名。
table:表名
lazy:这个属性用于指定是否需要延迟加载。
id标签
元素定义了该属性到数据库表主键字段的映射。
name:标识属性的名字。
column (可选 - 默认为属性名):主键字段的名字。
unsaved-value:用来指明对象未持久化时的值,如果此值与未持久化的对象标识值不符,将无法save对象
generator标签
用于指定标识对象的类型。
class:对象类型,常用值如下:
identity:用于MySql数据库。特点:递增。 注:对于MySql数据库使用递增序列时需要在建表时对主键指定为auto_increment属性。例:
<id name=\"id\" column=\"id\">
<generator class=\"identity\"/>
</id>
sequence:用于Oracle数据库。例:
<id name=\"id\" column=\"id\">
<generator class=\"sequence\">
<param name=\"sequence\">序列名</param>
</generator>
</id>
native:跨数据库时使用,由底层方言产生。Default.sequence为hibernate_sequence注:使用native时Hibernate默认会去查找Oracle中的hibernate_sequence序列。 如果Oracle中没有该序列,连Oracle数据库时会报错。例:
<id name=\"id\" column=\"id\">
<generator class=\"native\"/>
</id>
hilo:通过高低位合成id,先建表hi_value,再建列next_value。必须要有初始值(通过hi/lo 算法实现的主键生成机制,需要额外的数据库表保存主键生成历史状态)。例:
<id name=\"id\" column=\"id\">
<generator class=\"hilo\">
<param name=\"table\">high_val</param>
<param name=\"column\">nextval</param>
<param name=\"max_lo\">5</param>
</generator>
</id>
seqhilo:与hilo 类似,通过hi/lo 算法实现的主键生成机制,只是主键历史状态保存在Sequence中,适用于支持Sequence的数据库,如Oracle。
sequencehilo::同过高低位合成id,建一个sequence序列,不用建表。例:
<id name=\"id\" column=\"id\">
<generator class=\"hilo\">
<param name=\"sequence\">high_val_seq</param>
<param name=\"max_lo\">5</param>
</generator>
</id>
assigned:主键由外部程序负责生成,无需NHibernate参与。例:
<id name=\"id\" column=\"id\">
<generator class=\"assigned\"/>
</id>
foreign:用于一对一关系共享主健时,两id值一样。
increment:主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量,以保存着当前的最大值,之后每次需要生成主键的时候将此值加1作为主键。这种方式可能产生的问题是:如果当前有多个实例访问同一个数据库,那么由于各个实例各自维护主键状态,不同实例可能生成同样的主键,从而造成主键重复异常。因此,如果同一数据库有多个实例访问,此方式必须避免使用。
uuid.hex:由Hibernate基于128 位唯一值产生算法生成16 进制数值(编码后以长度32 的字符串表示)作为主键。
uuid.string:与uuid.hex 类似,只是生成的主键未进行编码(长度16)。在某些数据库中可能出现问题(如PostgreSQL)。