类图:
![](https://images.cnblogs.com/cnblogs_com/riccc/nhibernate_composite.gif)
表结构:
![](https://images.cnblogs.com/cnblogs_com/riccc/nhibernate_composite_table.gif)
xml配置:
<
hibernate-mapping
xmlns
="urn:nhibernate-mapping-2.2"
namespace
="ThoughtSoft.CMS.Box"
assembly
="thoughtsoft.cms"
>
< class name ="BoxParamDao" table ="Cms_Box_Param" >
< id name ="BoxParamId" >
< column name ="BOX_PARAM_ID" sql-type ="nvarchar2" length ="36" not-null ="true" />
< generator class ="assigned" />
</ id >
< property name ="BoxId" >
< column name ="BOX_ID" sql-type ="number(8,0)" not-null ="true" />
</ property >
< property name ="AttributeInfo" type ="ThoughtSoft.CMS.Box.BoxParamCompositeType, thoughtsoft.cms" >
< column name ="BOX_PARAM_TYPE" sql-type ="nvarchar2" length ="20" not-null ="true" />
< column name ="BOX_PARAM_NAME" sql-type ="nvarchar2" length ="20" not-null ="true" />
< column name ="BOX_PARAM_DESC" sql-type ="nvarchar2" length ="50" not-null ="false" />
< column name ="BOX_PARAM_LEN" sql-type ="nvarchar2" length ="50" not-null ="false" />
</ property >
< property name ="Value" >
< column name ="BOX_PARAM_VALUE" sql-type ="nvarchar2" length ="2000" not-null ="false" />
</ property >
</ class >
</ hibernate-mapping >
< class name ="BoxParamDao" table ="Cms_Box_Param" >
< id name ="BoxParamId" >
< column name ="BOX_PARAM_ID" sql-type ="nvarchar2" length ="36" not-null ="true" />
< generator class ="assigned" />
</ id >
< property name ="BoxId" >
< column name ="BOX_ID" sql-type ="number(8,0)" not-null ="true" />
</ property >
< property name ="AttributeInfo" type ="ThoughtSoft.CMS.Box.BoxParamCompositeType, thoughtsoft.cms" >
< column name ="BOX_PARAM_TYPE" sql-type ="nvarchar2" length ="20" not-null ="true" />
< column name ="BOX_PARAM_NAME" sql-type ="nvarchar2" length ="20" not-null ="true" />
< column name ="BOX_PARAM_DESC" sql-type ="nvarchar2" length ="50" not-null ="false" />
< column name ="BOX_PARAM_LEN" sql-type ="nvarchar2" length ="50" not-null ="false" />
</ property >
< property name ="Value" >
< column name ="BOX_PARAM_VALUE" sql-type ="nvarchar2" length ="2000" not-null ="false" />
</ property >
</ class >
</ hibernate-mapping >
使用NHibernate对BoxParamDao存取时,为BoxAttributeInfo类型实现一个ICompositeUserType接口 (ThoughtSoft.CMS.Box.BoxParamCompositeType)就可以。在HQL中可以这样查询:
IQuery query
=
session.CreateQuery(
"
from BoxParamDao t where t.BoxId=? and t.AttributeInfo.Name like ?
"
)
.SetInt32( 0 , 104 )
.SetString( 1 , " Title% " );
.SetInt32( 0 , 104 )
.SetString( 1 , " Title% " );
这里纠正一下 NHibernate考察系列 04 枚举 自定义类型 组件类型的 3. 自定义类型、自定义映射类型IUserType中的一个错误。那一段示例将一个DateTime类型的属性存储到数据库的两个CHAR类型字段 (CREATE_DATE、CREATE_TIME)中,而对这个属性实现了IUserType,因此在 NHibernate考察系列 05 Critetia, HQL, Native SQL, Named Query这一篇的 2. HQL部分,想在HQL中对这个属性进行查询时,没有办法进行。
上面这种做法是错误的。这种情况下这个DateTime属性完全是一个组合 (Composite)对象,应当定义一个组合类 (Composite Class),在存储映射时实现ICompositeUserType接口。
这样对ICompositeUserType和IUserType接口的职责就明确了:ICompositeUserType完全用于组合类型的映射;IUserType用于特殊属性的自定义映射。
虽然也可以使用IUserType接口实现单个属性映射到多个数据库字段,但这种情况下对于NHibernate来说,它只是一个简单类型的属性,而不是组合对象,你无法在HQL、Criteria中对这个属性进行条件查询。
其实从ICompositeUserType和IUserType接口本身也可以看出这个差别:ICompositeUserType要求实现public IType[] PropertyTypes()方法,返回组合对象的属性列表;并且要实现public object GetPropertyValue(object component, int property)、public void SetPropertyValue(object component, int property, object value),因为组合对象会具有多个属性。而IUserType只有一个public SqlType[] SqlTypes(),其实这个接口方法应该改为public SqlType SqlType()更合适,因为一个属性映射到多个字段,而又不是组合关系,这种使用方式很尴尬或者太特殊,并且一旦这样使用,HQL等其它一些特性又不支持,因此这是一个多余的设计,反而导致使用者对这个接口产生误解。