【问题标题】:dirty reads of associations in hibernate second level cache休眠二级缓存中关联的脏读
【发布时间】:2015-02-23 21:10:13
【问题描述】:

当启用 ehCache (2.7.0) 作为 Hibernate (4.3.7) 二级缓存时,Hibernate 返回旧的集合关联。

模型:会员拥有一个包含钱包交易的钱包。

场景:将钱包交易添加到交易中的成员(启用 ehcache)。但是,在场景之后(提交之后),Wallet 事务不存在于 Member 中,而存在于 db 中。

场景测试代码:

startTransaction(); // used to create a transaction through Spring.
member = findMemberById(); // Hibernate "get()" to retrieve member from Db.
final WalletTransaction walTx = member.getEnsureWallet().addWalletTransaction(10); // add wallet tx of 10 euro.
member.saveOrUpdate(); // will update the member and the wallet transactions through cascading
commitTransaction();

// assert wallet transaction is present
startTransaction();
final Taxer mem = findMemberById(member.getId()); // refresh member in session through it's PK, logging indicates it comes from cache.
// final Taxer mem = findMemberByLoginName(member.getLoginName()); // when retrieving the member through it's loginName, the test works.
assertTrue(mem.containsWalletTransaction(walTx)); // FAILS
commitTransaction();

休眠模型成员sn-p:

<class name="com.core.domain.MemberDefault" table="mem" discriminator-value="Mem" >
   <component name="wallet" class="com.core.domain.Wallet">
        <set name="transactions" table="wallet_tx" cascade="save-update, delete" >
            <!--cache usage="read-write" /-->
            <key column="idMember" not-null="true" />

            <composite-element class="com.core.domain.WalletTransactionDefault">
              <property name="amount" type="big_decimal" column="amount" />
               .... (more props)
            </composite-element>
        </set>
  </component>
</class

MemberDefault 和 WalletDefault 类 sn-ps:

public class MemberDefault implements Member {
  private Wallet wallet;
....
}

public class WalletDefault implements Wallet {
 private Set<WalletTransaction> transactions;

public void setTransactions(Set<WalletTransaction> transactions) {
  this.transactions = transaction;
 }

 public Set<WalletTransaction> getTransactions() {
  return this.transactions;
 }
}

注意事项:

  1. 万一我没有在一个交易中添加钱包交易(去掉第一个start/commit),测试成功(以上为重现bug的隔离测试代码)。
  2. 如果我关闭二级,测试就可以了。
  3. 如果我不是通过它的 PK 而是通过它的 loginName 从 Db 中检索成员,这样 Hibernate 会使用查询,并且查询缓存也是如此,那么测试就可以工作了。

我调试了,启用了 hibernate/ehcache 调试日志,修改了 hibernate 中的缓存设置,尝试了旧的 Hibernate 4 和 ehCache 版本,但似乎没有解决它,有点沮丧。

请给点建议如何解决这个问题?

【问题讨论】:

    标签: spring hibernate transactions ehcache


    【解决方案1】:

    我通过始终为 MemberDefault 中的钱包字段(休眠组件)分配一个实例来解决它。 也就是说,而不是:

    private Wallet wallet;
    

    我们不得不使用:

    private Wallet wallet = new WalletDefault();
    

    在 MemberDefault 类中。

    这是一个错误,还是有任何逻辑? 我认为这是一个错误,因为 Hibernate 知道它是来自 hibernate 配置的 WalletDefault 类型的组件。 (我是通过移除 Wallet 组件进行测试发现的)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-20
      • 2011-12-27
      • 2015-04-24
      • 2012-03-14
      • 2010-10-29
      • 2017-07-05
      • 2011-07-08
      相关资源
      最近更新 更多