Cache Inconsistency. An entity is not always stored in a cached collection.

I had a problem when a Validation instance was added to the Step instance collection. The declaration is as follows:

Class of steps:

 @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 have Cacheable with the READ_WRITE strategy READ_WRITE . The Validation unidirectional collection is also cached with the same strategy.

One would expect a read-write transaction calling addValidation(new Validation('userName')); commits, the new Validation will be visible in the subsequent read-only transaction. The strange thing is that sometimes it works, and sometimes it does not work ...

The first transaction is always successful; we see that the new check is stored in the database and the Step version property (for optimistic blocking navels), increasing. But sometimes the second read transaction contains an instance of Step with an empty Validation Collection ...

Hibernate caching configuration is as follows:

 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 causes this weird (and random) behavior?

+6
source share
1 answer

Hibernate Collection Cache always invalidates existing entries, and the Entity and Collection caches use the same AbstractReadWriteEhcacheAccessStrategy , so soft-lock is preserved when updating data.

Since you use a one-to-many unidirectional relationship, you end up with a Validation table and a Step_validation reference table. Whenever you add / remove validation, you have to hit two tables and do it less efficiently.

I suggest you add the @ManyToOne side to the Validation object and include the @OneToMany side in the associated collection:

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

Source: https://habr.com/ru/post/989406/


All Articles