第二级缓存集合状态有时不与数据库同步

时间:2015-11-18 14:00:30

标签: java hibernate jpa ehcache second-level-cache

我们在EhCache4.3.8.Final)中使用Hibernate作为二级缓存(4.3.8.Final)进行查询(仅限读取主要表),实体和实体之间的集合。

所以你可以说第二级缓存是为了优化目的而集中使用的。

到目前为止,我们从未遇到过任何重大问题......

我们关于相关实体的持久性模型基本如下:

  • 首先,我们有2个实体,其中有一个自然的亲子关系中的双向映射:

    @Entity
    @Table(...)
    @Cacheable
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    public class Parent extends BaseEntity {
        @Id
        private long id;
    
        @OneToMany(mappedBy="parent", fetch=FetchType.LAZY, cascade = CascadeType.REMOVE)
        @Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
        private Set<Child> children;
    
        // getters and setters
    }
    
    @Entity
    @Table(...)
    @Cacheable
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    public class Child extends BaseEntity {
        @Id
        private long id;
    
        @ManyToOne(fetch = FetchType.LAZY, optional = false)
        @JoinColumn(name = "parent_id", nullable = false)
        private Parent parent;
    
        // getters and setters
    }
    
  • 接下来我们有一些InvokingEntity,它与Parent实体的单向映射

         @Entity
         @Table(...)
         @Cacheable
         @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
         public class InvokingEntity extends BaseEntity {
             @Id
             private long id;
    
             @Fetch(FetchMode.SUBSELECT)
             @OneToMany(fetch = FetchType.LAZY, mappedBy = "invokingEntity", cascade = CascadeType.ALL, orphanRemoval = true)
             @OrderBy("sequence asc")
             @SortComparator(ParentBySequenceComparator.class)
             @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
             private Set<Parent> parents = new TreeSet<>();
    
             // getters and setters
         }
    

所有EntitiesBaseEntity延伸,其中包含idversion等常见属性,用于optimistic locking目的。


接下来会发生什么:

ChildRepository个应用程序删除所有Child个实体,然后创建新实体;这发生在同一个交易中(trx1):

删除方法的摘录:

 public void deleteChildsById(List<Long> childIds) {
    if (!childIds.isEmpty()) {
        getSession().createQuery("delete Child as child where child.id in (:childIds)")
                    .setParameterList("childIds", childIds)
                    .setReadOnly(false)
                    .executeUpdate();
    }
} 

创建方法的摘录:

public void createChilds(List<Child> childs) {
    for (Child child : childs) {
        getSession().save(child);
    }
}

之后,在第二个事务(trx2)中,子实体由自然实体图遍历检索:

InvokingEntity invokingEntity = getSession.get(InvokingEntity.class, someId);
Collection<Child> childs = invokingEntity.getFirstParent().getChilds();

现在,问题是childs集合有时是空的(在trx2中) 我们可以通过Child在数据库中清楚地看到多个trx1实体。

所以2nd level cache和DB之间显然不匹配。 同样,这个问题仅在大约10%的情况下发生。 同样不是trx2总是执行4-5秒 AFTER trx1

可能导致这种情况的原因是什么?映射,配置或查询问题?

Hibernate中存在一个问题,其中2nd level cache未被无效,但在早期版本上似乎已解决automatic L2 collection cache eviction when an element is added/updated/removed,而不是我们正在处理的问题。

为了完整起见,我在下面添加了ehcache配置的摘录:

    <defaultCache maxElementsInMemory="10000"
              eternal="false"
              timeToIdleSeconds="1800"
              timeToLiveSeconds="3600"
              overflowToDisk="true"
              diskPersistent="false"
              diskSpoolBufferSizeMB="10"
              diskExpiryThreadIntervalSeconds="120"
              memoryStoreEvictionPolicy="LRU">
    </defaultCache>

如果没有清楚解释的话,请随时询问! 我们为所有建议开放!

0 个答案:

没有答案