1

我有以下堆栈:

  • 休眠 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. 对于分配的@IduseIdentityColumn 为 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 论坛上发布了这个问题,但没有太大的兴趣。

4

1 回答 1

1

我也认为这对于二级缓存的使用是一个很大的限制,所以我创建了一个问题(HHH-7964)。我还添加了一条带有解决方法的评论,但这只是一个概念证明,据我所知不应用于生产。

于 2013-02-01T21:58:42.347 回答