今日の役に立たない一言 - Today’s Trifle! -

古い記事ではさまざまなテーマを書いていますが、2007年以降はプログラミング関連の話がほとんどです。

Hibernateで更新するときにNonUniqueObjectExceptionが発生

Hibernateでデータを更新しようとしたら、NonUniqueObjectExceptionというのが発生した。

    public Hoge update(Hoge hoge) {
        Session session = sessionFactory.getCurrentSession();
        try {
            Hoge h = (Hoge)session.get(Hoge.class, hoge.getId());
            hoge.setServerOnly(h.getServerOnly());
            session.update(hoge);
            session.flush();
            session.refresh(hoge);
        } catch (Exception e) {
            throw e;
        }
        return hoge;
    }

クライアントから受け取ったエンティティをそのまま update() に渡せばうまく動くのかもしれないけど、ここで受け取ってるエンティティはクライアントが変更している一部だけしか設定されていないので、足りないデータをサーバー側で補完してから保存する必要がある。

NonUniqueObjectException ってのは、ひとつのセッションの中で同一のエンティティを複数あつかったときに発生するらしい。

This exception is thrown when an operation would break session-scoped identity. This occurs if the user tries to associate two different instances of the same Java class with a particular identifier, in the scope of a single Session.

NonUniqueObjectException (Hibernate API Documentation)

ということは、DBから取得した方のインスタンスを使えばいい?
DBから取得したインスタンスに対して、クライアントから受け取ったデータを設定するように変更してみた。

    public Hoge update(Hoge hoge) {
        Session session = sessionFactory.getCurrentSession();
        try {
            Hoge h = (Hoge)session.get(Hoge.class, hoge.getId());
            h.setFromClient1(hoge.getFromClient1());
            h.setFromClient2(hoge.getFromClient2());
            session.update(h);
            session.flush();
            session.refresh(h);
        } catch (Exception e) {
            throw e;
        }
        return hoge;
    }

あっさり解決。