简体   繁体   English

缓存不一致 - 实体并不总是保留在缓存的Collection中

[英]Cache inconsistency - Entity not always persisted in cached Collection

I'm having an issue where a Validation instance is added to a Collection on a Step instance. 我遇到一个问题,即在Step实例上将Validation实例添加到Collection。 Declaration is as follows: 声明如下:

Step class: 步骤类:

@Entity
@Table
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Step extends AbstractEntity implements ValidatableStep {

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "step_id", nullable = false)
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    private Set<Validation> validations = new HashSet<>();

    @Override
    public void addValidation(Validation validation) {
      // do some stuff
      ...
      // add validation instance to collection
      getValidations().add(validation);
    }

}

Validation class: 验证类:

@Entity
@Table
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Validation extends AbstractEntity {
  //some properties
}

Both classes are Cacheable with a READ_WRITE strategy applied. 这两个类都是Cacheable ,并且应用了READ_WRITE策略。 The unidirectional Collection of Validation s are also cached with same strategy. 单向的Validation集合也使用相同的策略进行缓存。

One would expect when a read-write transaction that invokes addValidation(new Validation('userName')); 当读取事务调用addValidation(new Validation('userName'));时,人们会期待addValidation(new Validation('userName')); commits, the new Validation would be visible in a subsequent read-only transaction. 提交时,新的Validation将在后续的只读事务中可见。 The weird thing is that sometimes it does work and sometimes it doesn't work... 奇怪的是,有时它确实有效,有时它不起作用......

The first transaction always succeeds; 第一笔交易总是成功; we see the new validation being persisted in database and Step 's version property (for optimistic locking puposes) getting incremented. 我们看到新的验证在数据库中持久存在,而Step的版本属性(用于乐观锁定目的)会增加。 But sometimes, the 2nd read transaction contains a Step instance with an empty Validation Collection... 但有时,第二个读取事务包含一个带有空Validation Collection的Step实例...

Our Hibernate caching config is as follows: 我们的Hibernate缓存配置如下:

hibernate.cache.use_second_level_cache = true
hibernate.cache.use_query_cache = true
hibernate.cache.region.factory_class = org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
hibernate.cache.provider_configuration_file_resource_path = classpath:ehcache.xml
net.sf.ehcache.hibernate.cache_lock_timeout = 10000

Any idea what's causing this weird (and random) behavior? 知道造成这种奇怪(和随机)行为的原因是什么?

The Hibernate Collection Cache always invalidates existing entries and both the Entity and the Collection caches are sharing the same AbstractReadWriteEhcacheAccessStrategy , so a soft-lock is acquired when updating data. Hibernate Collection Cache总是使现有条目无效,Entity和Collection缓存共享相同的AbstractReadWriteEhcacheAccessStrategy ,因此在更新数据时会获得软锁

Because you are using a unidirectional one-to-many association, you will end up with a Validation table and a Step_validation link table too. 因为您使用的是单向一对多关联,所以最终会得到Validation表和Step_validation链接表。 Whenever you add/remove a Validation you have to hit two tables and that's less efficient. 无论何时添加/删除验证,您都必须点击两个表并且效率较低。

I suggest you adding the @ManyToOne side in the Validation entity and turn the @OneToMany side into a mapped-by collection: 我建议您在Validation实体中添加@ManyToOne端,并将@OneToMany端转换为映射集合:

@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "step")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Set<Validation> validations = new HashSet<>();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM