最近一个老项目,模型结构是这样的
QualifiedEntity
<class name="QualifiedRole">
.....
<map name="qualifiedEventRole" cascade="all"
table="VERIFIED_ROLES_MAP">
<key column="QUALIFIED_ROLE_ID" not-null="false" />
<map-key-many-to-many column="EVENT_ID" class="VerifiedEvent" />
<many-to-many column="ROLE_ID" class="Role" />
</map>
</class>
这样映射出来,会产生中间表,关联QualifiedRole主键及Role主键。并且QualifiedRole主键和VerifiedEvent的EVENT_ID作为联合主键。
现在需求变了,VerifiedEvent的id 可以关联多个role, 而不再是以前的1对1关系。所以看起来,应该对这样的模型进行映射
Map<VerifiedEvent, List<<Role>>, 不过查询了hibernate文档之后,不能直接对这样的结构进行映射。而采取把Map里面的 value:List<Role>放到一个新的wrapper类,再进行映射,如下:
<class name="QualifiedRole">
.....
<map name="qualifiedEventRole" cascade="all"
table="VERIFIED_ROLES_MAP">
<key column="QUALIFIED_ROLE_ID" not-null="false" />
<map-key-many-to-many column="EVENT_ID" class="VerifiedEvent" />
<many-to-many column="WRAPPER_ROLE_ID" class="WrapperRole" />
</map>
</class>
<class name="WrapperRole">
<id>**** </id>
<list>
<key column="WRAPPER_ROLE_ID" />
<list-index column="LIST_INDEX" />
<one-to-many class="Role" />
</list>
</class>
虽然这样能解决问题,但是在一个运行很久的系统来说,这样会造成数据表的变化,那么以前大量的老数据如何迁移?
基于以上考虑,决定使用一个新类: QualifiedEventRole,并利用它关联以前的Key和Value 对象,至于mapping,以映射Set的方式,即可重用以前的表结构。模型变化如下:
<class name="QualifiedRole">
.....
<set name="qualifiedEventRole" table="VERIFIED_ROLES_MAP"></set>
</class>
总结:以这种方式实现重构,表结构无任何变化,还是和以前一样,3张表:QualifiedRole, VerifiedEvent, Role以及一个中间表VERIFIED_ROLES_MAP,但以前的Key: VerifiedEvent对象,满足了需求,实现了对多个Role的依赖,不再有唯一约束。
在老数据很大,关系较负责的情况下,要考虑数据迁移的难度。能不变表结构实现重构,这样的方式,只需要修改domain模型相关代码,升级相对简单。