第二章:NHibernate配置的总体流程

摘要:
在上一章中,我们了解了NHibernate的介绍和使用。如何将NHibernate引入项目并使用?让我们开始本章的操作!首先,你需要准备:1。下载NHibernate:当前版本2.0.1下载地址:http://sourceforge.net/projects/nhibernate/2.下载CodeSmith:http://www.codesmithtools.com/3.下载NHibernate模板:https://files.cnblogs.com/abluedog/nhibernate_template.rar关于NHibernate 2.1的一些注意事项:NHibernate2.1更改了ByteCode延迟加载机制。IoC框架有三种动态代理方法,即Castle框架、LinFu框架和Spring。网络框架。

  上一章节,我们了解了NHibernate的介绍和用途,那NHibernate如何引入到项目中,并且被运用呢,这一章我们开始操作吧!

  注:本材料开始本人研究3天研究出来的,绝对最新,请仔细阅读!!!

  首先要有准备工作:

  1、下载NHibernate:当前版本2.0.1(较新版本)下载地址:http://sourceforge.net/projects/nhibernate/

  2、下载CodeSmith:http://www.codesmithtools.com/
  3、下载NHibernate模板:https://files.cnblogs.com/abluedog/nhibernate_template.rar

  

  关于NHibernate2.1版本的一些说明:

NHibernate2.1版本改变了ByteCode延迟加载机制,有三种3种IoC框架动态代理方式,分别为:Castle框架、LinFu框架、Spring.Net框架。我们只要选择一种,在配置文件中配置proxyfactory.factory_class节点。

如果使用Castle.DynamicProxy2动态代理,引用NHibernate.ByteCode.Castle.dll程序集并配置proxyfactory.factory_class节点为<property name="proxyfactory.factory_class"> NHibernate.ByteCode.Castle.ProxyFactoryFactory,NHibernate.ByteCode.Castle</property>

如果使用LinFu.DynamicProxy动态代理,引用NHibernate.ByteCode.LinFu.dll程序集并配置proxyfactory.factory_class节点为<property name="proxyfactory.factory_class"> NHibernate.ByteCode.LinFu.ProxyFactoryFactory,NHibernate.ByteCode.LinFu</property>

如果使用Spring.Aop动态代理,引用NHibernate.ByteCode.Spring.dll程序集并配置proxyfactory.factory_class节点为<property name="proxyfactory.factory_class"> NHibernate.ByteCode.Spring.ProxyFactoryFactory,NHibernate.ByteCode.Spring</property>

另外NHibernate2.1要求.NET2.0 SP1以上版本 (System.DateTimeOffset),请使用VS2005的,务必打上Sp1补丁。推荐使用VS2008以上版本。

  OK,准备工作结束,开始讲解如何运用这3个工具:

  首先打开CodeSmith(注意CodeSmith一定要注册),导入NHibernate模板:如图

  第二章:NHibernate配置的总体流程第1张

  注意:我在网上搜索很多关于NHibernate模板,始终没有找到,这个模板算是比较好的,但是要修改一下类生成文件和映射生成文件的内容:

  1、打开NHibernate.class.cst,找到如下代码:把所有生成 get、set 的 public修饰符改为 publicvirtual ,注绿色virtual为添加部分

  

第二章:NHibernate配置的总体流程第2张第二章:NHibernate配置的总体流程第3张代码
#region Public Properties

<% if (SourceTable.PrimaryKey.MemberColumns.Count == 1) {%>
public virtual <%= IdMemberType(SourceTable) %> <%= IdName(SourceTable) %>
{
get {return <%= IdMemberName(SourceTable) %>;}
<% if (IdMemberType(SourceTable) == "string" ) {%>
set
{
if ( value != null && value.Length > <%= ColumnLength(SourceTable.PrimaryKey.MemberColumns[0])%>)
throw new ArgumentOutOfRangeException("Invalid value for <%= IdName(SourceTable) %>", value, value.ToString());
<%= IdMemberName(SourceTable) %> = value;
}
<% } else { %>
set {<%= IdMemberName(SourceTable) %> = value;}
<% } %>
}
<% } %>

<% foreach(ColumnSchema column in SourceTable.NonKeyColumns) { %>
public virtual <%= MemberType(column) %> <%= PropertyName(column) %>
{
get { return <%= MemberName(column) %>; }
<% if (MemberType(column) == "string") {%>
set
{
if ( value != null && value.Length > <%= ColumnLength(column)%>)
throw new ArgumentOutOfRangeException("Invalid value for <%= PropertyName(column) %>", value, value.ToString());
<%= MemberName(column) %> = value;
}
<% } else { %>
set { <%= MemberName(column) %> = value; }
<% } %>
}

<% } %>
<% foreach(TableKeySchema foreignKey in SourceTable.ForeignKeys) { %>
public <%= ManyToOneClass(foreignKey) %> <%= ManyToOneName(foreignKey) %>
{
get { return <%= ManyToOneMemberName(foreignKey) %>; }
set { <%= ManyToOneMemberName(foreignKey) %> = value; }
}

<% if ((foreignKey.ForeignKeyTable == SourceTable) && (foreignKey.PrimaryKeyTable == SourceTable)) { %>
public virtual <%= CollectionType(foreignKey) %> <%= CollectionName(foreignKey) %>
{
get { return <%= CollectionMemberName(foreignKey) %>; }
set { <%= CollectionMemberName(foreignKey) %> = value; }
}

<% } %>
<% } %>
<% foreach(TableKeySchema primaryKey in SourceTable.PrimaryKeys) { %>
<% if (IsManyToManyTable(primaryKey.ForeignKeyTable)) { %>
public virtual <%= CollectionType(primaryKey) %> <%= CollectionManyToManyName(primaryKey) %>
{
get
{
if (<%= CollectionManyToManyMemberName(primaryKey) %>==null)
{
<%= CollectionManyToManyMemberName(primaryKey) %> = <%= NewCollectionType(primaryKey) %>;
}
return <%= CollectionManyToManyMemberName(primaryKey) %>;
}
set { <%= CollectionManyToManyMemberName(primaryKey) %> = value; }
}

<% } else if (IsOneToOneTable(primaryKey)) { %>
public virtual <%= OneToOneClass(primaryKey) %> <%= OneToOneName(primaryKey) %>
{
get { return <%= OneToOneMemberName(primaryKey) %>; }
set { <%= OneToOneMemberName(primaryKey) %> = value; }
}

<% } else if (IsSubClassTable(primaryKey)) { %>
<% } else { %>
public virtual <%= CollectionType(primaryKey) %> <%= CollectionName(primaryKey) %>
{
get
{
if (<%= CollectionMemberName(primaryKey) %>==null)
{
<%= CollectionMemberName(primaryKey) %> = <%= NewCollectionType(primaryKey) %>;
}
return <%= CollectionMemberName(primaryKey) %>;
}
set { <%= CollectionMemberName(primaryKey) %> = value; }
}

<% } %>
<% } %>


#endregion

  

  2、打开NHibernate.hbm.cst,映射由2.0改为2.2 

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class<%= ClassNameAtt(SourceTable) %><%= ClassTableAtt(SourceTable) %>>

  OK,NHibernate模板修改成功,开始生成实体与映射文件

  最近在做一个进销存联系,数据表多了点,不利于学习,但是你看明白了,可以做一个数据表的小例子,下面是数据表的截图:

  第二章:NHibernate配置的总体流程第4张

  生成持久化类 与 映射文件

  右键NHibernate.cst点击Execute,出现下面界面

  第二章:NHibernate配置的总体流程第5张

  OutputDirectory:你的实体与映射文件保存的文件夹,建议先保存到一个单独的文件夹;

  SourceDatabase:是你第一次选择时需要配置一个连接字符串,配置好后Code Smith将记录下来;

  Assembly:写上你的项目的实体类库名,比如我做的进销存,实体类库叫GoodsMnanage.Model,在以后的Configuration创建时需要加载这个名字;

  Namespace:写上你的实体文件产生的路径。

   如果不明白可以对比一下我的项目截图:

  第二章:NHibernate配置的总体流程第6张

  开始配置项目

  开发工具:vs2005/vs2008,SQL2005

  首先建一个小的web项目,以往的材料全是简单的实体和一个控制台文件,今天我们运用到3层的web项目中:

  根据截图,我们可以在Model层中建2个文件夹,所有***.cs类全部放在Entities文件夹中

注意:NHibernate默认使用代理功能,要求持久化类不是sealed的,而且其公共方法、属性和事件声明为virtual。

也就是说所有生成属性的set、get方法必须写成下面这种类型:检查一下你的实体类是这样写的吗,这就是为什么我们要修改NHibernate模板成为Public Virture了

public virtual string Name
  {
    get { return name; }
    set{ name = value;}
  }

在这里,类中的字段要设置为virtual,否则出现“failed: NHibernate.InvalidProxyTypeException : The following types may not be used as proxies: NHibernateSample.Domain.Entities.Customer: method get_Id should be virtual,method set_Id should be virtual”异常。

  所有***.hbm.xml映射文件全部放在Mappings文件夹中;

注意:所有Mapping下的***.hbm.xml的属性中生成的操作默认生成操作为“内容”,这里需要修改为“嵌入的资源”生成,因为NHibernate是通过查找程序集中的资源文件               映射实体;否则出现“ failed: NHibernate.MappingException : No persister for: NHibernateSample.Domain.Entities.Customer”异常

  然后在DAO层中首先添加版本为2.0.1中的NHibernate.dll,然后建一个NHibernateHelper.cs类

  

第二章:NHibernate配置的总体流程第7张第二章:NHibernate配置的总体流程第8张代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Cfg;

namespace GoodsManage.DAO
{
public static class NHibernateHelper
{
private static ISession session = null;
private static ITransaction trans = null;

/// <summary>
///获取打开的session
/// </summary>
/// <returns></returns>

public static ISession getSession()
{
      //这里的GoodsManage.Model就是我们在CodeSmith中配置生成文件时的Assembly中的内容
Configuration conf
= new Configuration().AddAssembly("GoodsManage.Model");
//建立工厂
      ISessionFactory factory = conf.BuildSessionFactory();
      //打开工厂
session
= factory.OpenSession();

return session;
}

/// <summary>
/// 获取事务
/// </summary>
/// <returns></returns>
public static ITransaction getTrans()
{
      //创建事务
trans
= session.BeginTransaction();
return trans;
}
}
}

  之后新建类写增删改查的方法,写个简单的Get方法:

public static TbUser getUserById(int userId)
{
TbUser user
= session.Get<TbUser>(userId);
return user;
}

  之后建DAL层,添加DAO的应用

public static TbUser getUserById(int userId)
{
TbUser user
= tb_UserServer.getUserById(userId);
return user;
}

  最后开始最后一层,表示层,最重要的就是web.config的配置:

  首先要在表示层添加DAO、DAL的应用,最重要的是添加NHibernate.ByteCode.Castle.dll的引用

   web.config的配置

第二章:NHibernate配置的总体流程第9张第二章:NHibernate配置的总体流程第10张代码
<configuration>
<configSections>
<section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate"/>
</configSections>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.connection_string">Server=.;DataBase=db_GoodsManage;user id=sa;password=123456</property>
<property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
</session-factory>
</hibernate-configuration>
<appSettings/>
<connectionStrings/>

  dialect:数据库版本,我用的Sql2005,如果是2000,可以写MsSql2000Dialect

  connection.provider:连接数据库的提供者Nhibernate

  connection.connection_string:连接数据库字符串

  proxyfactory.factory_class:(关于NHibernate2.1.0的说明)

注意:如果没有配置proxyfactory.factory_class,会出现:

The ProxyFactoryFactory was not configured.
Initialize 'proxyfactory.factory_class' property of the session-factory configuration section with one of the available NHibernate.ByteCode providers.
Example:
<property name='proxyfactory.factory_class'>NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property>
Example:
<property name='proxyfactory.factory_class'>NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>

  最后在新建一个页面:添加一个按钮,双击按钮

protected void Button1_Click(object sender, EventArgs e)
{
TbUser user
= tb_UserManage.getUserById(1);
Response.Write(
"<script>alert('" + user .Name + "')</script>");
}

 运行,点击按钮时

第二章:NHibernate配置的总体流程第11张

  好了,结束了,我们的总体配置NHibernate流程也告一段落了,希望大家能够看懂,我开始学习HQL了,希望早点学会,总结大家看,如果本节存在什么问题,请大家指出,感谢大家的支持!

免责声明:文章转载自《第二章:NHibernate配置的总体流程》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇MySQL 中随机抽样:order by rand limit 的替代方案32. Springboot 系列(八)动态Banner与图片转字符图案的手动实现下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Hibernate 数据的批量插入、更新和删除

4.2  Hibernate的批量处理 Hibernate完全以面向对象的方式来操作数据库,当程序里以面向对象的方式操作持久化对象时,将被自动转换为对数据库的操作。例如调用Session的delete()方法来删除持久化对象,Hibernate将负责删除对应的数据记录;当执行持久化对象的set方法时,Hibernate将自动转换为对应的update方法,修...

HIBERNATE锁机制

乐观锁与悲观锁  文章转自网上好像是玉米田的,忘记了锁( locking ) 业务逻辑的实现过程中,往往需要保证数据访问的排他性。如在金融系统的日终结算 处理中,我们希望针对某个 cut-off 时间点的数据进行处理,而不希望在结算进行过程中 (可能是几秒种,也可能是几个小时),数据再发生变化。此时,我们就需要通过一些机 制来保证这些数据在某个操作过程中不...

Hibernate-入门教程

首先了解hibernate的目录结构 . +lib antlr.jar cglib-full.jar asm.jar asm-attrs.jars commons-collections.jar commons-logging.jar ehcache.jar hibernate3.jar jta....

Java高并发,如何解决,什么方式解决

  对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了。而并发问题是绝大部分的程序员头疼的问题,但话又说回来了,既然逃避不掉, 那我们就坦然面对吧~今天就让我们一起来研究一下常见的并发和同步吧。   为了更好的理解并发和同步,我们需要先明白两个重要的概念:同步和异步    1、同步和异步的区别和联系    所谓同步,可以...

JPA或Hibernate中的

JPA执行原生SQL截断Char类型问题 在JPA的API中执行原生SQL:EntityManager.createNativeQuery(String sqlString);传入参数是原生SQL语句,返回SQL对象。 如果oracle数据库中某个字段定义的是char类型,比方说是char[2],当使用EntityManager.createNativeQ...

Hibernate的批量处理

  Hibernate完全以面向对象的方式操作数据库,当程序员以面向对象的方式操作持久化对象时,将自动转换为对数据的操作。例如我们Session的delete()方法,来删除持久化对象,Hibernate将负责删除对应的数据记录;当我们执行持久化对象的setter方法时,Hibernate将自动转换为底层的update语句,修改数据库的对应记录。   问题...