我有以下堆栈:
- 休眠 3.6.9.Final
- 春天 3.1.1
- Atomikos 3.7.1
- Infinispan 4.2.1.FINAL
- MySQL
我一直在编写一些测试,以确保当抛出 RuntimeException 时,当前事务会在数据库上回滚,但也会在事务性 2LC 上回滚。
我发现了一些奇怪的结果,希望有人能解释一下。
如果我使用带有 @Cache(usage=CacheConcurrencyStrategy.TRANSACTIONAL) 注释的 @Entity 和字符串 @Id,我会在分配 id 并保存实体时看到我期望的结果:
- 当没有抛出异常时,事务被提交并且 2LC 包含实体,我使用以下方法确认了这一点:
sessionFactory.getCache().containsEntity(MyEntity.class, myIdentifier)
- 如果抛出异常,则数据库或 2LC 都不包含该实体。
@Entity
但是,如果我使用生成的@Id
(MySQL 自动递增长属性)重复这些测试,如图所示:
@Id
@GeneratedValue
private long id;
我发现实体永远不会被放入 2LC,无论抛出任何异常。
我已经进行了一些调试,这似乎取决于AbstractSaveEventListener#performSaveOrReplicate
. 对于分配的@Id
useIdentityColumn 为 false,因此我们实例化并执行 EntityInsertAction,然后将新实体放入 2LC。
相反,如果@Id
由 MySQL 生成,我们发现 useIdentityColumn 为真,我们实例化并执行 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 论坛上发布了这个问题,但没有太大的兴趣。