在hibernate中 以Collection<Entity> 替换Map<Key, List<Value>结构

最近一个老项目,模型结构是这样的

QualifiedEntity


mapping 文件

<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">
            <key column="QUALIFIED_ROLE_ID" not-null="false" />
            <composite-element class="VerifiedApplicationRole">
                <many-to-one name="verificationEvent" class="VerifiedEvent" column="EVENT_ID"/>
                <many-to-one name="role" class="Role" column="ROLE_ID"/>
            </composite-element>

</set>

</class>


总结:以这种方式实现重构,表结构无任何变化,还是和以前一样,3张表:QualifiedRole, VerifiedEvent, Role以及一个中间表VERIFIED_ROLES_MAP,但以前的Key: VerifiedEvent对象,满足了需求,实现了对多个Role的依赖,不再有唯一约束。

在老数据很大,关系较负责的情况下,要考虑数据迁移的难度。能不变表结构实现重构,这样的方式,只需要修改domain模型相关代码,升级相对简单。

要将List<Entity>转化为List<Map<Object, Object>>,可以使用以下方法: 1. 首先,我们需要创建一个空的List<Map<Object, Object>>来存储转化后的结果。 2. 然后,我们遍历原始的List<Entity>的每个实体对象。 3. 对于每个实体对象,我们需要创建一个空的Map<Object, Object>来存储转化后的键值对。 4. 我们使用反射获取实体对象的所有get方法,并遍历每个get方法。 5. 对于以"get"开头的方法名,我们将其截取后面的属性名,并将首字母转为小写,用作Map的键。 6. 使用反射调用get方法获取实体对象对应属性的值。 7. 如果属性的返回类型是java.util.Date,并且值不为null,则将日期格式化为指定的格式(比如"yyyy-MM-dd HH:mm:ss")。 8. 将属性名作为键,属性值作为值,存入Map。 9. 将转化后的Map添加到结果的List。 10. 最后返回转化后的List<Map<Object, Object>>。 下面是一个示例的代码实现,用于将List<Entity>转化为List<Map<Object, Object>>: ``` public static <T extends IdEntity> List<Map<Object, Object>> EntityConvertMap(List<T> list) { List<Map<Object, Object>> result = new LinkedList<>(); try { for (T entity : list) { Map<Object, Object> map = new HashMap<>(); Method[] methods = entity.getClass().getMethods(); for (Method method : methods) { if (method.getName().startsWith("get")) { String name = method.getName().substring(3); name = name.substring(0, 1).toLowerCase() + name.substring(1); Object value = method.invoke(entity); if (method.getGenericReturnType().toString().equals("class java.util.Date") && value != null) { value = getNow((Date) value, "yyyy-MM-dd HH:mm:ss"); } map.put(name, value); } } result.add(map); } } catch (Exception e) { e.printStackTrace(); } return result; } ``` 这样,你就可以使用该方法将List<Entity>转化为List<Map<Object, Object>>了。<span class="em">1</span><span class="em">2</span>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值