四、使用代码生成工具CodeSmith生成NHibernate实体模型和对象关系映射文件
关于NHibernate的ORM映射这里不作描述,可以参考Nhibernate官方的参考手册,或是网络上其他文档,这里主要就快速开发的角度来解决问题。当我们探讨理论的时候,我们研究配置,当我们开发的时候就不可能每个类和每个映射文件都去手动编写了。
我使用的版本是CodeSmith Professional 4.1,不同的版本可能编写的模板不同,当然,我们可以更改这些模板的代码,从而生成更加符合我们要求的实体模型和映射文件
1. 打开CodeSmith
2.在打开后的界面后边找到CodeSmith自带的Nhibernate模板
3.这里,我们要对NHibernate.hbm.cst这个模板作作些代码调整
打开NHibernate.hbm.cst模板,将模板中的<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">该成<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
修改原因:
我的NHibernate发行包(NHibernate-2.0.1.GA)的nhibernate-mapping.xsd文件中明确指出hbm文件的目标命名空间是” urn:nhibernate-mapping-2.2”
Default-lazy的缺省值是true,在C#里面这意味着要求模型类的所有属性方法必须为virtual修饰符号,因为NHibernate的延迟特性要采用代理机智完成,这个和Java不一样,Java里面的实例方法本身就是虚方法。在这里,模型的生成的代码当中并没有将所有属性标记为virtual修饰符号,因此是矛盾的,解决方法有多种,如果想很好利用NHibernate的延迟加载特性,应该修改这个模板,将所有属性和方法加上virtual修饰符号,也可以直接加上default-lazy="false",这样就不用修改模板了,当然弊端也很明显。
4.使用模板向导生成代码
4.1.在NHibernate.cst上面鼠标右键à Execute
出现下面向导
对上面的属性作如下解释:
OutputDirectory:代码输出目录,这里我们指定为我们的实体模型这个项目的物理位置
SourceDatabase:选择数据源的向导,根据向导操作连接到Oracle数据库
Assembly:类所在的程序集的名字,我们指定为当前项目的名字:OfficeModel
ForceId:是否对于标识列强制使用Id命名,如果为true,那么所有的主键列都被映射成Id属性,我们选择false
Namespace:类的命名空间,我仍然采用OfficeModel
RemoveTablePrefix:要删除的表前缀,我的表没有前缀,我设置为空.
4.2.上面的工作做完了后,我们点击下面的Generate按忸,开始生成代码
下面是生成后的代码:
4.3.编译生成后的项目,发现出现错误,在项目上添加对System.Web的引用(原因根据错误提示得知)
至此,代码生成工作告一段落,我们可以关闭CodeSmith。
4.4.根据需要更改映射文件
这里,我需要修改对象OID值的生成方式为Oracle的Sequence
USER_INFO.hbm.xml文件:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false" schema="MACK"> <class name="OfficeModel.USERINFO, OfficeModel" table="USER_INFO"> <id name="Id" type="Int32" unsaved-value="0"> <column name="USER_ID" sql-type="NUMBER"/> <generator class="sequence"> <param name="sequence">SEQ_USER_ID</param> </generator> </id> <property name="USERNAME" type="String"> <column name="USER_NAME" length="16" sql-type="VARCHAR2" not-null="true"/> </property> </class> </hibernate-mapping>
MESSAGE.hbm.xml文件:
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false" schema="MACK"> <class name="OfficeModel.MESSAGE, OfficeModel" table="MESSAGE"> <id name="Id" type="Int32" unsaved-value="0"> <column name="MSG_ID" sql-type="NUMBER" not-null="true" unique="true" index="SYS_C002717"/> <generator class="sequence"> <param name="sequence">SEQ_MSG_ID</param> </generator> </id> <property name="MSGCONTENT" type="String"> <column name="MSG_CONTENT" length="1000" sql-type="VARCHAR2" not-null="false"/> </property> <property name="MSGTIME" type="DateTime"> <column name="MSG_TIME" sql-type="DATE" not-null="false"/> </property> <many-to-one name="SEND_" class="OfficeModel.USERINFO, OfficeModel"> <column name="SEND_USER_ID" sql-type="NUMBER" not-null="false"/> </many-to-one> <many-to-one name="REC_" class="OfficeModel.USERINFO, OfficeModel"> <column name="REC_USER_ID" sql-type="NUMBER" not-null="false"/> </many-to-one> </class> </hibernate-mapping>
5、最后非常郑重地声明一点,这里所有的.hbm.xml文件必须设置属性"生成操作"的值为"嵌入的资源",NHibernate 的API会从实体模型的程序集中读取这些映射文件