web-dev-qa-db-ja.com

HibernateがNULL値を更新しないようにするにはどうすればよいですか?

Hibernateオブジェクトを保存するときにプロパティのnull値を無視するにhibernateに設定はありますか?

[〜#〜] note [〜#〜]
私の場合、JSONをJackson経由でHibernatePojoに逆シリアル化しています。

JSONには、Pojoの一部のフィールドのみが含まれています。 Pojoを保存すると、JSONになかったフィールドはPojoでnullになり、休止状態で更新されます。

updateable=falseの設定に出くわしましたが、これは100%の解決策ではありません。 http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-mapping-property

多分誰かが別のアイデアを持っています...

注2:

Hibernate Docsによると、dynamicUpdateannotationはまさにそれを実行します

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アノテーションを無視しているようです。

19
Jeremy S.

最初にDBから主キーを使用してオブジェクトをロードしてから、その上にJSONをコピーまたは逆シリアル化する必要があります。

値がnullのプロパティが明示的にその値に設定されているのか、それとも除外されているのかを休止状態で判断する方法はありません。

挿入の場合、dynamic-insert = trueが機能するはずです。

12
gkamal

私はこれについてたくさんグーグルで検索しましたが、私にとっての解決策はありません。それで、私はそれをカバーするために優雅ではない解決策を使用しました。

  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に更新したくありません。 dbからtmp Obejctを取得し、メソッドgetNotNullでフィールドを変更してから、オブジェクトを更新します。

中国語の説明版

0
Acceml

私はこの問題にぶつかり、これを解決するための回避策を実行しました。少し醜いかもしれませんが、あなたにとってもうまくいくかもしれません。誰かが気になったら、気軽に追加しておくとよい調整があります。回避策は、有効なエンティティクラスを対象としており、一部のフィールドにnull許容属性が含まれていることに注意してください。これの利点は、クエリの数が減ることです。

_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のフィールド:userIduserNameuserAge; getUpdateJPQL(user, userId, 2)の結果クエリは_update User t set t.userName = 'value1', t.userAge = 'value2' where t.userId = 2_である必要があります。userIdフィールドで_@JsonIgnore_のようなjsonアノテーションを使用して、逆シリアル化、つまり生成されたクエリで除外できることに注意してください。その後、entityManagerまたは休止状態のセッションを使用してクエリを実行できます。

0
Xstarz