È possibile aggiornare l'entità nel database senza modificare la versione dell'entità utilizzando l'ibernazione?È possibile disattivare l'incremento della versione di ibernazione per un particolare aggiornamento?
Utilizzando la mia applicazione Web, gli utenti possono creare o aggiornare entità. E dove c'è un altro processo asincrono che "elabora" queste entità dopo ogni operazione dell'utente. Se l'utente apre l'entità per l'aggiornamento prima che l'entità sia "elaborata", ma tenta di salvarla dopo che è stata "elaborata", l'utente otterrà "OptimisticLockException" e tutti i dati inseriti verranno persi. Ma vorrei sovrascrivere i dati aggiornati in processo asincrono con i dati forniti dall'utente.
pezzo di codice presentato per dimostrare il motivo per cui ho bisogno di tale comportamento (JPA + Hibernate):
//user creates entity by filling form in web application
Entity entity = new Entity();
entity.setValue("some value");
entity.setProcessed (false);
em.persist(entity);
em.flush();
em.clear();
//but after short period of time user changes his mind and again opens entity for update
entity = em.find(Entity.class, entity.getId());
em.clear(); //em.clear just for test purposes
//another application asynchronously updates entities
List entities = em.createQuery(
"select e from Entity e where e.processed = false")
.getResultList();
for (Object o: entities){
Entity entityDb = (Entity)o;
someTimeConsumingProcessingOfEntityFields(entityDb); //update lots of diferent entity fields
entityDb.setProcessed(true);
em.persist(entityDb);
}
em.flush(); //version of all processed entities are incremented.
//Is it possible to prevent version increment?
em.clear();
//user modifies entity in web application and again press "save" button
em.merge(entity); //em.merge just for test purposes
entity.setValue("some other value");
entity.setProcessed (false);
em.persist(entityDb);
em.flush(); //OptimisticLockException will occur.
//Is it possible to prevent this exception from happening?
//I would like to overwrite data updated in asynchronous process
//with user provided data.
E il mio soggetto:
@Entity
@Table(name = "enities")
public class Entity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Version
private int versionNum;
@Column
private String value
@Column
private boolean processed;
//… and so on (lots other properties)
}
In realtà ho molto di più classi con problemi simili - così ho Sto cercando una soluzione elegante non invadente.
Mi sembra questo scenario abbastanza usuale. Ma non sono riuscito a trovare alcuna informazione su come ottenere tale funzionalità.
Questa soluzione disattiverà completamente il controllo di blocco ottimistico, quindi più utenti modificano la stessa entità utilizzando l'interfaccia web, ma non voglio che ciò accada. Il problema non è quindi l'utente aggiorna l'entità, ma il processo asincrono aggiorna l'entità. Quindi penso di aver bisogno in qualche modo di modificare l'aggiornamento dell'entità nel processo asincrono. – Palladium
È inoltre possibile associare l'entità a una classe diversa senza l'attributo di versione e utilizzarla esclusivamente nella chiamata asincrona. – Brian
Sì, funzionerebbe, ma sfortunatamente ciò richiederebbe un sacco di refactoring extra (ridisegnare completamente le mie classi di dominio). Nella mia applicazione tutte le classi di dominio (più di 100 classi) estende la super classe con la versione fieldNum e una parte significativa di esse viene aggiornata con alcuni processi asincroni. Quindi cambiare dominio per questa particolare ragione sarebbe una soluzione molto "intrusiva". In tal caso, penso che sarebbe più facile sovrascrivere la classe DefaultFlushEntityEventListener di hibernate con possibilità di girare l'incremento della versione in alcuni casi (ma ciò significa "ramificazione" di ibernazione). – Palladium