私は次のスタックを持っています:
- 休止状態 3.6.9.Final
- 春 3.1.1
- アトミコス 3.7.1
- インフィニスパン 4.2.1.FINAL
- MySQL
RuntimeException がスローされたときに、現在のトランザクションがデータベースだけでなくトランザクション 2LC でもロールバックされることを確認するために、いくつかのテストを書いています。
誰かが説明してくれることを望んでいた奇妙な結果がいくつか見つかりました。
@Cache(usage=CacheConcurrencyStrategy.TRANSACTIONAL) で注釈が付けられた @Entity を String @Id とともに使用すると、ID を割り当ててエンティティを保存すると、期待どおりの結果が得られます。
- 例外がスローされず、トランザクションがコミットされ、2LC にエンティティが含まれている場合、次を使用してこれを確認しました。
sessionFactory.getCache().containsEntity(MyEntity.class, myIdentifier)
- 例外がスローされた場合、データベースにも 2LC にもエンティティが含まれていません。
@Entity
ただし、示されているように、生成された@Id
(MySQL 自動インクリメント long プロパティ)を持つを使用してこれらのテストを繰り返すと:
@Id
@GeneratedValue
private long id;
スローされた例外に関係なく、エンティティが 2LC に配置されることはありません。
私はいくつかのデバッグを行いましたAbstractSaveEventListener#performSaveOrReplicate
. 割り当てられた@Id
useIdentityColumn は false であるため、EntityInsertAction をインスタンス化して実行し、新しいエンティティを 2LC に配置します。
逆に、@Id
MySQL によって生成された場合、useIdentityColumn が true であることがわかり、EntityIdentityInsertAction をインスタンス化して実行します。これには、次のように 2LC に関するコメント アウトされたコードが含まれています。
//TODO: this bit actually has to be called after all cascades!
//but since identity insert is called *synchronously*,
// instead of asynchronously as other actions, it isn't
/*if ( persister.hasCache() && !persister.isCacheInvalidationRequired() ) {
cacheEntry = new CacheEntry(object, persister, session);
persister.getCache().insert(generatedId, cacheEntry);
}*/
これには何か理由がありますか?キャッシュの挿入は別の場所で行う必要がありますか? これはバグですか?
誰かがこの違いとこれがどのように機能するかについて何か光を当てることができれば、私は非常に感謝しています.
この質問を Hibernate フォーラムに投稿しましたが、あまり興味がありませんでした。