session.createSQLQuery で更新すると、2次キャッシュが全部フラッシュされる

Query query = session.createSQLQuery("UPDATE foobar SET value = ? WHERE id = ?");

query.setInteger(0, newValue);
query.setLong(1, id);

query.executeUpdate();

などとしてcreateSQLQueryを使ってUPDATE文を実行すると、Hibernateの2次キャッシュが「全部」フラッシュされてしまった。まぁHibernateにとっては、どんな更新なのかよくわからんもの実行されたら全部フラッシュするしか一貫性を保つことできないもんなぁ。

SELECT文なら大丈夫なようなので、DB側に update_foobar という関数を作って SELECT 文で実行してやると、2次キャッシュがフラッシュされることなく更新できた。

Query query = session.createSQLQuery("SELECT update_foobar(?, ?)");

query.setInteger(0, newValue);
query.setLong(1, id);

Integer result = (Integer) query.uniqueResult();

この場合2次キャッシュの一貫性は自分で保たないといけなくなるので、SessionFactory.evict や evictQueries などを適宜実行する必要がありますね。


Hibernateのバージョンは3.2.5.ga、2次キャッシュはOSCache/2.4.1とEHCache/1.3.0で確認。