NHibernate中ICompositeUserType和IUserType的区别
使用NHibernate实现ICompositeUserType后,可以在HQL中对组合对象的属性进行查询,例如下面
类图:
表结构:
xml配置:
使用NHibernate对BoxParamDao存取时,为BoxAttributeInfo类型实现一个ICompositeUserType接口(ThoughtSoft.CMS.Box.BoxParamCompositeType)就可以。在HQL中可以这样查询:
这里纠正一下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等其它一些特性又不支持,因此这是一个多余的设计,反而导致使用者对这个接口产生误解。
类图:
表结构:
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等其它一些特性又不支持,因此这是一个多余的设计,反而导致使用者对这个接口产生误解。