个人对Spring 在java平台下的运用比较熟悉。并且已经是一年前了。
重拾Spring,但选择的是 Spring.Net 。
Java 平台下 Spring+Hibernate 是公认的黄金组合。
.NET 平台下 Spring.Net+NHibernate 也是企业架构最有前途的组合之一。
早前使用Hibernate 比较烦人的就是 编写实体关系映射的 XML 描述文件。
后来在Hibernate 3 以后就开始不再使用XML 改用 Annotation 注解,有点类似 Attributes 的方式。
同样 NHibernate 也有类似 Annotation 的实现。
在NHibernateContrib 项目下有一个子集 NHibernate.Mapping.Attributes 它可以使得我们不在编写XML 。
我在使用 Spring.Net+NHibernate 时发现 Spring.Net IOC 容器在创建 NHibernateSessionFactory
的时候只支持从程序集读取XML来加载对象映射关系,使得我们无法直接使用 Attributes。
解决办法
自定义一个 类 继承自 Spring.Data.NHibernate.LocalSessionFactoryObject
重写 父类的 AfterPropertiesSet() 方法
具体实现代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using NHibernate.Mapping.Attributes;
namespace Dao.RepositoryDao
{
public class MyLocalSessionFactoryObject : Spring.Data.NHibernate.LocalSessionFactoryObject
{
public MyLocalSessionFactoryObject()
{
}
/// <summary>
/// 实体类所在程序集的名称
/// </summary>
public string[] ModelAssemblyNames
{
get;
set;
}
/// <summary>
/// 将实体类所配置的Attributes转换成XML流添加至Configuration
/// </summary>
private void AddInputStream()
{
MemoryStream stream = new MemoryStream();
NHibernate.Mapping.Attributes.HbmSerializer.Default.Validate = true;
foreach (string modelAssemblyName in ModelAssemblyNames)
{
Assembly assembly = Assembly.Load(modelAssemblyName);
HbmSerializer.Default.Serialize(stream, assembly);
stream.Position = 0;
base.Configuration.AddInputStream(stream);
}
}
/// <summary>
/// 重写父类AfterPropertiesSet
/// </summary>
public override void AfterPropertiesSet()
{
base.AfterPropertiesSet();
AddInputStream();
}
}
}
在Spring.Net 的配置文件中 使用自定义的 LocalSessionFactoryObject 类
<object id="NHibernateSessionFactory" type="Dao.RepositoryDao.MyLocalSessionFactoryObject, Dao.RepositoryDao">
<property name="DbProvider" ref="DbProvider"/>
<!--自定义LocalSessionFactoryObject中的属性 指实体类所在程序集的名称-->
<property name="ModelAssemblyNames">
<list>
<value>Domain.Model</value>
</list>
</property>
<property name="HibernateProperties">
<dictionary>
<entry key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/>
<entry key="dialect" value="NHibernate.Dialect.MsSql2000Dialect"/>
<entry key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver"/>
<entry key="use_outer_join" value="true"/>
<entry key="show_sql" value="false"/>
<entry key="adonet.batch_size" value="10"/>
<entry key="command_timeout" value="60"/>
<entry key="query.substitutions" value="true 1, false 0, yes 'Y', no 'N"/>
<entry key="proxyfactory.factory_class" value="NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle"/>
</dictionary>
</property>
<property name="ExposeTransactionAwareSessionFactory" value="true" />
</object>