你如何改变NHibernate中行的子类型?例如,如果我有一个Customer实体和TierOneCustomer的子类,我有一个案例需要将Customer更改为TierOneCustomer,但TierOneCustomer应该具有与原始Customer实体相同的Id(PK).
映射看起来像这样:
... properties snipped ... ... more properties ...
我正在使用每个类的单表层次结构模型,因此使用plain-sql,只需要对鉴别器(CustomerType)进行sql更新,并设置与该类型相关的相应列.我无法在NHibernate中找到解决方案,所以会感激任何指针.
考虑到这个用例,我也在考虑模型是否正确,但在我沿着这条路走下去之前,我想确保首先按照上述方式进行操作.如果没有,我几乎肯定会考虑改变模型.
简而言之,您可以使用本机SQL更改特定行的鉴别器值.
但是,我认为NHibernate并不打算以这种方式工作,因为鉴别器通常对Java层是"不可见的",其值应该根据持久对象的类最初设置并且永远不会改变.
我建议采用更清洁的方法.从对象模型的角度来看,您尝试将超类对象转换为其子类类型之一,同时不更改其持久化实例的标识,这就是冲突的位置(转换后的对象实际上不应该是同一件事情).两种替代方法是:
根据原始Customer对象中的信息创建TierOneCustomer的新实例,然后删除原始对象.如果您依靠客户的主键进行检索,则需要注意新的PK.
要么
更改您的方法,以便对象类型(鉴别器)不需要更改.您可以使用可以随时自由修改的属性,即Customer.Tier = 1,而不是依赖子类来区分TierOneCustomer和Customer.
以下是可能感兴趣的Hibernate论坛的一些相关讨论:
我们可以更新Hibernate中的discriminator列吗?
每类表问题:判别器和属性
将持久化实例转换为子类
你做错了什么.
您要做的是更改对象的类型.你不能用.NET或Java做到这一点.这根本没有意义.对象只是一种具体类型,其具体类型不能从创建对象到对象被销毁时更改(尽管是黑魔法).为了完成您要执行的操作,但是使用您布置的类层次结构,您必须销毁要转换为第一层客户对象的客户对象,创建新的第1层客户对象,并将客户对象中的所有相关属性复制到第一层客户对象.这就是您使用类层次结构在面向对象语言中使用对象的方法.
显然,您拥有的类层次结构并不适合您.当他们成为一线客户时,您不会摧毁现实生活中的客户!所以不要用对象做.相反,考虑到您需要实现的方案,提出一个有意义的类层次结构.您的使用场景包括:
以前不是第一级状态的客户现在变为第一级状态.
这意味着您需要一个可以准确捕获此场景的类层次结构.作为提示,你应该赞成合成而不是继承.这意味着,根据最有效的方法,拥有一个名为IsTierOne
property的属性或一个名为的属性DiscountStrategy
等可能是更好的主意.
NHibernate(和Hibernate for Java)的全部目的是使数据库不可见.为了让您可以本机地使用对象,可以在数据库中神奇地使用数据库来使对象持久化.NHibernate将允许您本地使用数据库,但这不是为NHibernate构建的场景类型.