NHibernate 学习
1. hibernate.cfg.xml 配置文件 (主要是数据库链接和关联映射文件)
<?xmlversion="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<propertyname="connection.driver_class">
NHibernate.Driver.SqlClientDriver
</property>
<propertyname="connection.connection_string">
Uid=sa;Pwd=`1234qwert;Initial Catalog=T_DZ;Data Source=10.163.100.173
</property>
<propertyname="dialect">
NHibernate.Dialect.MsSql2008Dialect
</property>
<propertyname="show_sql">
true
</property>
<mappingassembly="NhibernatePro" />
<!--关联 hbm文件的 assembly-->
</session-factory>
</hibernate-configuration>
注意: 该文件的输出方式必须设置成: 始终复制
2. Domain 和 hbm 文件的声明
(1) 有两个表 Product 和 Category 表,表结构如下
(2) 对应的两个 Domain 如下:
Category.cs
namespace NhibernatePro.App_Code.Domain { [Serializable] public class Category {
public virtual string CategoryId {
get;
set;
}
public virtual string CategoryName {
get;
set;
}
public virtual IList < Product > ProductList {
get;
set;
}
//用于一对多的关联,一个Category对应多个Product
}
}
Product.cs
namespace NhibernatePro.App_Code.Domain { [Serializable] public class Product {
public virtual string ProductId {
get;
set;
}
public virtual string ProductName {
get;
set;
}
public virtual decimal ProductProce {
get;
set;
}
public virtual Category Category {
get;
set;
}
//多对一的关联一个Product属于一个Category
}
}
备注: 属性必须定义成 virtual 的.
(3) Hbm 映射文件的定义
Hbm 文件的名称必须和 Domain 的名称一样
Hbm 文件的生成操作必须设置成嵌入的资源
Eg: Category 对应的映射文件名称为: Category.hbm.xml
Category.hbm.xml
<?xmlversion="1.0" encoding="utf-8" ?>
<hibernate-mappingxmlns="urn:nhibernate-mapping-2.2" assembly="NhibernatePro"
namespace="NhibernatePro.App_Code.Domain">
<classname="Category" table="Category">
<idcolumn="CategoryId" name="CategoryId" type="string">
<generator class="assigned">
</generator>
</id>
<propertyname="CategoryName" type="string">
<columnname="CategoryName">
</column>
</property>
<bag name="ProductList" cascade="all" lazy="true" inverse="true">
<key column="CId" not-null="false" />
<one-to-many class="Product">
</one-to-many>
</bag>
<!--一对多的配置 1. cascade 配置 可以保证在存Category时级联存Product. ,也可以在删除category时级联删除product
2. lazy=true 延迟加载,因为分类下有很多产品,所以需要设置级联,这里需要保证session没有关闭,以便在级联取数据时不会报session关闭的错误.
3. inverse=true 默认的inverse为false表示关联关系由外键表维护即Product表,true表示由主键表维护,即Category.在级联删除时必须设置为true
-->
</class>
</hibernate-mapping>
Product.hbm.xml
<?xmlversion="1.0" encoding="utf-8" ?>
<hibernate-mappingxmlns="urn:nhibernate-mapping-2.2" assembly="NhibernatePro"
namespace="NhibernatePro.App_Code.Domain">
<classname="Product" table="Product">
<idcolumn="ProductId" name="ProductId" type="string">
<generatorclass="assigned">
</generator>
</id>
<propertyname="ProductName" type="string">
<columnname="ProductName">
</column>
</property>
<propertyname="ProductProce" type="decimal">
<columnname="ProductProce">
</column>
</property>
<many-to-one name="Category" column="CId" not-null="false" cascade="save-update"
lazy="false">
</many-to-one>
<!-- 1. 多对一两边的column均为外键表中的关联外键 2. cascade="save-update" 保证在新建和保存Product时可以级联保存和更新Category
3. lazy=false 表示非延迟加载,在取product数据时就把category数据也取出来(这样可以防止session关闭后通过p.Category.CategoryName取数时报session关闭)
-->
</class>
</hibernate-mapping>
3. Hibernate 工具类,用于获取 Session 和关闭链接
namespace NhibernatePro.App_Code.Utility {
classHibernateHelper {
ISession session = null;
publicISession GetSession() {
if (null == session || !(session.IsOpen)) {
Configuration config = new Configuration().Configure("hibernate.cfg.xml");
ISessionFactory sessionFactory = config.BuildSessionFactory();
session = sessionFactory.OpenSession();
}
return session;
}
public void Close(ISession session) {
if (null != session) {
session.Flush();
session.Clear();
session.Close();
}
}
}
}
4. 数据访问层
(1) 通用接口
namespace NhibernatePro.App_Code.DAL {
public interface IDAL < T > {
void Add(T t);
T Get(string id);
void Update(T t);
void Delete(string id);
IList < T > ListAll();
IList < T > ListByPage(int currPage, int pageSize);
Int32 Count < T > ();
}
}
(2) ProductDAL对IDAL的实现
namespace NhibernatePro.App_Code.DAL {
public class ProductDAL: IDAL < Product > {
HibernateHelper hh = new HibernateHelper();
//添加一个Product
public void Add(Product t) {
try {
ISession session = hh.GetSession();
ITransaction trans = session.BeginTransaction();
session.SaveOrUpdate(t);
trans.Commit();
hh.Close(session);
} catch(Exception ex) {
ex.StackTrace.ToString();
}
}
//获取一个Product
public Product Get(string id) {
ISession session = hh.GetSession();
Product product = session.Get < Product > (id);
hh.Close(session);
return product;
}
//更新
public void Update(Product t) {}
//删除
public void Delete(string id) {
Product p = Get(id);
ISession session = hh.GetSession();
session.Delete(p);
hh.Close(session);
}
//获取全部的Product
public IList < Product > ListAll() {
ISession session = hh.GetSession();
IList < Product > productList = session.CreateQuery("from Product").List < Product > ();
hh.Close(session);
return productList;
}
//分页获取
public IList < Product > ListByPage(int currPage, int pageSize) {
ISession session = hh.GetSession();
IQuery query = session.CreateQuery("from Product");
//query.SetParameter(0,"value1"); //设置hql的参数,下标从0开始
query.SetFirstResult((currPage - 1) * pageSize); //分页的开始位置
query.SetMaxResults(pageSize); //一页有多少条
IList < Product > productList = query.List < Product > ();
hh.Close(session);
return productList;
}
//获取总条数
public int Count < T > () {
Int32 count = 0;
ISession session = hh.GetSession();
IQuery query = session.CreateSQLQuery("select count(*) from Product");
count = (Int32) query.UniqueResult();
return count;
}
}
}
(备注)对于有添加更新删除的操作,应该先开启事物,最后在提交
5.业务层BLL
该层直接调用DAL层中的方法.
6.测试使用NUnit进行测试用NUnit加载项目生成的exe文件,即可看到如下的测试方法.
namespace NhibernatePro.App_Code.Test { [TestFixture] class TestCase { [Test] public void ListCategory() {
CategoryBLL categoryBLL = new CategoryBLL();
IList < Category > categoryList = categoryBLL.ListAll();
if (null != categoryList) {
foreach(Category c in categoryList) {
Console.WriteLine(c.CategoryName);
IList < Product > productList = c.ProductList;
foreach(Product p in productList) {
Console.WriteLine(p.ProductName + ":" + p.ProductProce);
}
Console.WriteLine();
}
}
} [Test] public void ListProduct() {
ProductBLL productBLL = new ProductBLL();
IList < Product > productList = productBLL.ListAll();
if (null != productList) {
foreach(Product p in productList) {
Console.WriteLine("{0},{1},{2}", p.ProductName, p.ProductProce, p.Category.CategoryName);
}
}
} [Test] public void listByPage() {
ProductBLL productBLL = new ProductBLL();
Int32 currPage = 1;
Int32 pageSize = 5;
IList < Product > productList = productBLL.ListByPage(currPage, pageSize);
if (null != productList) {
foreach(Product p in productList) {
Console.WriteLine("{0},{1},{2}", p.ProductName, p.ProductProce, p.Category.CategoryName);
}
}
} [Test] public void getProduct() {
ProductBLL productBLL = new ProductBLL();
string productId = "AE93D4DF-1650-4E12-BE0A-EF698E6E1127";
Product p = productBLL.Get(productId);
if (null != p) {
Console.WriteLine("{0},{1},{2}", p.ProductName, p.ProductProce, p.Category.CategoryName);
}
} [Test]
//保存一个product它的category是已经存在的
public void saveProduct1() {
CategoryBLL categoryBLL = new CategoryBLL();
string categoryId = "aed459a5-2c0a-441f-a019-2c2b389a7fcd";
Category category1 = categoryBLL.Get(categoryId);
Product p = new Product();
p.ProductId = Guid.NewGuid().ToString();
p.ProductName = "banana";
p.ProductProce = new decimal(15);
p.Category = category1;
ProductBLL productBLL = new ProductBLL();
CategoryBLL categoryBll = new CategoryBLL();
// categoryBll.Add(category1);
productBLL.Add(p);
}
//保存一个product它的category需要级联添加
[Test] public void saveProductWithCategory() {
Category c = new Category() {
CategoryId = Guid.NewGuid().ToString(),
CategoryName = "Water"
};
Product p = new Product() {
ProductId = Guid.NewGuid().ToString(),
ProductName = "EverGreat Ice Water",
ProductProce = new decimal(500),
Category = c
};
ProductBLL productBLL = new ProductBLL();
CategoryBLL categoryBll = new CategoryBLL();
productBLL.Add(p);
}
//删除一个product
[Test] public void deleteProdcut() {
string productId = "e0ccd2f1-dd26-4dca-bb39-ff318c297fff";
ProductBLL productBLL = new ProductBLL();
productBLL.Delete(productId);
Console.WriteLine("删除成功....");
}
//删除一个category (会级联删除该category下的product)
[Test] public void deleteCategory() {
string categoryId = "7fc0a318-9031-4683-bf5d-1de0c5ee4680";
CategoryBLL categoryBLL = new CategoryBLL();
categoryBLL.Delete(categoryId);
Console.WriteLine("删除Category成功..");
} [Test] public void countProduct() {
ProductBLL productBLL = new ProductBLL();
Int32 pCount = productBLL.Count < Product > ();
Console.WriteLine("count:" + pCount);
}
}
}
7. 项目的完整结构如下:
来源: http://lib.csdn.net/article/dotnet/35952