如何使用Map <string,string>类型的元素集合更新实体?

时间:2018-12-13 13:11:53

标签: java spring hibernate orm

在我的Spring Boot应用程序中,我有一个像这样的实体类:

public class MyEntity {
    String id;
    Map<String,String> paramsMap;
    //Many members omitted
}

相关的JPA ORM XML代码段是

<entity class="MyEntity" access="FIELD">
    <table name="myentity">
       <!--couple of unique-constraints-->
    </table>
    <attributes>
        <element-collection name="paramsMap" fetch="EAGER">
            <collection-table name="my_entity_params">
                <join-column name="id" />
            </collection-table>
        </element-collection>
    </attributes>
</entity>

这近似于this question

的答案

我的问题是类MyEntity的实体需要更新,包括params映射的内容。发生这种情况时,Oracle DB返回一个异常,表明已违反表my_entity_params的主键唯一约束(PostgreSQL静默地无法更新某些参数)。

更新的大概方式是:

public void updateParam(String id, String paramName, String paramValue){
    MyEntity old=repository.findById(id)
    old.getParamsMap().put(paramName, paramValue);
    repository.save(old);
}

repository在其中实现了接口PagingAndSortingRepository

如果在调用paramsMap之前未修改save,则更新成功。我尝试先设置paramsMap,先保存然后再保存实际地图,这会导致相同的错误。

使用one-to-many无效,因为地图没有指向复杂的类型。同样,Eclipse Foundation Wiki的How to map collections of Basic or Emeddable values using an ElementCollection mapping文章并未阐明如何在地图上使用元素集合。

map-key-column下插入element-collection元素似乎可以解决Postgres中的问题,但是当连接到Oracle数据库时问题仍然存在。

如何让Hibernate正确更新地图内容?

1 个答案:

答案 0 :(得分:0)

看来我有两个症状相似的问题。

首先,我在map-key-column下缺少元素element-collection,因此Spring无法正确构造更新查询。通过更改如下元素可以解决此问题:

<element-collection name="paramsMap" fetch="EAGER">
  <map-key-column name="my_entity_params_key"/>
  <collection-table name="my_entity_params">
    <join-column name="id" />
  </collection-table>
</element-collection>

第二个问题是Oracle treats empty strings as null,这导致系统进一步混乱,并尝试在已存在键空对的情况下插入键值对。通过在插入/更新之前从映射中删除空字符串值来解决此问题。