21

hibernate 中是否有设置在保存休眠对象时忽略属性的空值?

注意
在我的例子中,我通过 Jackson 将 JSON 反序列化为 Hibernate Pojo。

JSON 仅包含 Pojo 的一些字段。如果我保存 Pojo,则不在 JSON 中的字段在 Pojo 中为空并休眠更新它们。

我遇到了设置updateable=false,但这不是 100% 的解决方案。 http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-mapping-property

也许有人有另一个想法......

笔记2:

根据 Hibernate Docs,dynamicUpdate 注释正是这样做的

dynamicInsert / dynamicUpdate(默认为 false):
指定 INSERT / UPDATE SQL 应在运行时生成,并且仅包含值不为 null的列。

http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-class

有趣的是,如果您通过dynamic-update文档在 XML 中定义它,请不要提及 NULL 值的处理。

动态更新(可选 - 默认为 false):
指定 UPDATE SQL 应该 > 在运行时生成,并且只能包含值已更改的那些列。

由于我同时使用注释xml 配置,hibernate 似乎忽略了我的dynamicUpdate=true注释。

4

3 回答 3

14

您应该首先使用数据库中的主键加载对象,然后在其上复制或反序列化 JSON。

hibernate 无法确定值为 null 的属性是否已显式设置为该值或已被排除。

如果它是插入,那么 dynamic-insert=true 应该可以工作。

于 2011-09-22T17:49:55.887 回答
0

我对此进行了很多搜索,但没有适合我的解决方案。所以,我使用了一个不优雅的解决方案来涵盖它。

  public void setAccount(Account a) throws HibernateException {
    try {
        Account tmp = (Account) session.
                get(Account.class, a.getAccountId());
        tmp.setEmail(getNotNull(a.getEmail(), tmp.getEmail()));            
        ...
        tmp.setVersion(getNotNull(a.getVersion(), tmp.getVersion()));
        session.beginTransaction();
        session.update(tmp);
        session.getTransaction().commit();
    } catch (HibernateException e) {
        logger.error(e.toString());
        throw e;
    }
}

public static <T> T getNotNull(T a, T b) {
    return b != null && a != null && !a.equals(b) ? a : b;
}

我收到一个Object a包含很多字段的字段。可能是那些字段null,但我不想将它们更新到 mysql 中。我tmp Obejct从数据库中得到一个,并通过方法更改字段getNotNull,然后更新对象。

中文说明版

于 2016-01-08T03:22:14.897 回答
0

我遇到了这个问题,我做了一个解决方法来帮助自己解决这个问题。可能有点难看,但也可能对你有用。如果有人觉得有一个很好的调整,可以随意添加。请注意,该解决方法适用于有效的实体类,并且其某些字段包含可为空的属性。这个的优点是它减少了查询的数量。

public String getUpdateJPQL(Object obj, String column, Object value) throws JsonProcessingException, IOException {

//obj -> your entity class object
//column -> field name in the query clause
//value -> value of the field in the query clause

    ObjectMapper mapper = new ObjectMapper();
    String json = mapper.writeValueAsString(obj);
    Map<String, Object> map = mapper.readValue(json, Map.class);
    Map format = new HashMap();
    if (value instanceof String) {
        value = "'" + value + "'";
    }

    map.keySet()
            .forEach((str) -> {
                Object val = map.get(str);
                if (val != null) {
                    format.put("t.".concat(str), "'" + val + "'");
                }
            });
    String formatStr = format.toString();
    formatStr = formatStr.substring(1, formatStr.length() - 1);

    return "update " + obj.getClass()
            .getSimpleName() + " t set " + formatStr + " where " + column + " = " + value + "";

}

示例:对于User具有字段的实体类型:userId, userName& userAge; 的结果查询getUpdateJPQL(user, userId, 2)应该是update User t set t.userName = 'value1', t.userAge = 'value2' where t.userId = 2 注意,您可以使用像@JsonIgnoreonuserId字段这样的 json 注释在反序列化中排除它,即在生成的查询中。然后,您可以使用 entityManager 或休眠会话运行查询。

于 2019-08-20T10:24:05.983 回答