2015-06-19 1 views
6

У меня возникла проблема, когда экземпляр Validation добавлен в коллекцию на экземпляр Step. декларация выглядит следующим образом:Непоследовательность кэша. Объект не всегда сохраняется в кэше. Коллекция

Шаг Класс:

@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 класс:

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

Оба класса Cacheable с READ_WRITE стратегии применяются. Однонаправленная коллекция Validation с также кэшируется с той же стратегией.

Можно было бы ожидать, когда транзакция чтения и записи, которая вызывает addValidation(new Validation('userName'));, совершит, новый Validation будет виден в последующей транзакции только для чтения. Странно то, что иногда он работает, а иногда он не работает ...

Первая транзакция всегда преуспевает; мы видим, что новая валидация сохраняется в базе данных и свойство версии Step (для оптимистичных блокирующих пупок) увеличивается. Но иногда, вторая транзакция чтения содержит Step экземпляра с пустым Validation Коллекции ...

Нашего 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 

Любой идея, что вызывает это странное (и случайное) поведение?

ответ

1

Hibernate Collection Cache всегда делает недействительными существующие записи, и оба кеша Entity и Collection совместно используют один и тот же AbstractReadWriteEhcacheAccessStrategy, поэтому soft-lock is acquired при обновлении данных.

Поскольку вы используете однонаправленную связь «один-ко-многим», в итоге вы получите таблицу Validation и таблицу ссылок Step_validation. Всякий раз, когда вы добавляете/удаляете проверку, вам нужно нажать две таблицы, и это менее эффективно.

Я предлагаю вам добавлять @ManyToOne стороны в Validation сущности и повернуть @OneToMany стороны в отображенном-коллекции:

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

На самом деле, у меня нет таблицы ссылок. У проверки есть только внешний ключ к шагу. Таким образом, add/remove должен запускать только одну таблицу. Во всяком случае, я сделал свои отношения двунаправленными, и это сделало трюк! Однако я не понимаю, почему кеш второго уровня требует двунаправленного отношения? Мое приложение полон одно направленное (потому что bi не всегда имеет смысл). Означает ли это, что мне приходится реорганизовывать все отношения? Я использую во всех коллекциях стратегию кэширования NONSTRICT_READ_WRITE или READ_WRITE ... – user2054927

+0

«Step» является родителем ассоциации, а «Validation» является Child. В отношениях «Родитель-ребенок» Родитель является стороной «один-ко-многим», и его лучше сопоставлять. Часто вы можете превратить это в однонаправленную связь, которая требует удаления стороны «один-ко-многим» и оставления только ассоциации «один-ко-многим». Однонаправленная связь «один-ко-многим» всегда использует таблицу ссылок, и это не очень практично. –

+0

Thx для уточнения этого! – user2054927

Смежные вопросы