Sto riscontrando un problema in cui un'istanza Validation
viene aggiunta a una raccolta su un'istanza Step
. dichiarazione è la seguente:Incoerenza nella cache - L'entità non è sempre persistente nella raccolta cache
Passo classe:
@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);
}
}
classe di convalida:
@Entity
@Table
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Validation extends AbstractEntity {
//some properties
}
Entrambe le classi sono Cacheable
con una strategia READ_WRITE
applicata. Anche la raccolta unidirezionale di Validation
s viene memorizzata nella cache con la stessa strategia.
Ci si aspetterebbe quando una transazione di lettura/scrittura che richiama addValidation(new Validation('userName'));
si impegna, il nuovo Validation
sarà visibile in una successiva transazione di sola lettura. La cosa strana è che a volte funziona e talvolta non funziona ...
La prima operazione ha sempre esito positivo; vediamo che la nuova convalida è persistita nel database e la proprietà della versione di Step
(per le approssimazioni del blocco ottimistico) viene incrementata. Ma a volte, la seconda transazione di lettura contiene un'istanza Step
con una Validation
Collection vuoto ...
nostro Hibernate caching configurazione è la seguente:
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
Qualche idea di cosa sta causando questo strano (e casuale) comportamento?
In realtà, non ho una tabella di collegamento. La validazione ha solo una chiave straniera per Step. Quindi un add/remove dovrebbe attivare solo una tabella. Ad ogni modo, ho reso il mio rapporto bidirezionale e questo ha fatto il trucco! Tuttavia, non capisco perché la cache di secondo livello richiede una relazione bidirezionale? La mia applicazione è piena di quelli direzionali (perché bi non è sempre significativo). Questo significa che devo refactoring tutte le relazioni? Uso su tutte le raccolte una strategia di memorizzazione nella cache NONSTRICT_READ_WRITE o READ_WRITE ... – user2054927
Il 'Passo' è il genitore dell'associazione e' Validazione' è il bambino. In una relazione padre-figlio, il genitore è il lato uno-a-molti ed è anche meglio mapparlo. Spesso, è possibile trasformarlo in un'associazione unidirezionale, che richiede la rimozione del lato uno-a-molti e lasciando solo l'associazione many-to-one. Un'associazione unidirezionale uno-a-molti usa sempre una tabella dei collegamenti e non è molto pratica. –
Thx per chiarire questo! – user2054927