当启用ehCache(2.7.0)作为Hibernate(4.3.7)二级缓存时,Hibernate会返回旧的集合关联。
型号:会员拥有一个包含电子钱包交易的电子钱包。
场景:将Wallet交易添加到交易中的成员(启用了ehcache)。但是,在场景之后(提交之后),会员中的钱包交易不存在,而它在数据库中存在。
测试代码的方案:
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();
hibernate模型成员代码段
<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类摘要:
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;
}
}
注意:
我调试了,启用了hibernate / ehcache调试日志,修改了hibernate中的缓存设置,尝试了较旧的Hibernate 4和ehCache版本,但似乎没有解决它,有点令人沮丧。
请就如何解决这个问题提出一些建议?
答案 0 :(得分:0)
我通过总是将一个实例分配给MemberDefault中的wallet字段(hibernate组件)来解决它。 也就是说,而不是:
private Wallet wallet;
我们必须使用:
private Wallet wallet = new WalletDefault();
在MemberDefault类中。
这是一个错误,还是有任何逻辑? 我认为这是一个错误,因为Hibernate知道它是来自hibernate配置的WalletDefault类型的组件。 (我通过删除Wallet组件进行测试来发现它)