Is it possible update entity in database without modifying version of entity using hibernate?
Using my web application users can create or update entities. And where is another asynchronous process which “processes” these entities after any user operation. If user opens entity for update before entity is “processed”, but tries to save it after it is “processed”, user will get “OptimisticLockException” and all his entered data will be lost. But I would like to overwrite data updated in asynchronous process with user provided data.
code snipet to demonstrate why I need such behaviour (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.
And my entity:
@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 reality I have much more classes with similar problem - so I am looking for some elegant non intrusive solution.
It seems to me this is quite usual scenario. But I could not find any information how to achieve such functionality.
update() method updates the entity for persistence using the identifier of detached object or new instance of entity created with existing identifier. If the object is already in the session with the same identifier, then it throws exception.
When ever we use versioning then hibernate inserts version number as zero, when ever object is saved for the first time in the database. Next time when we update this object, hibernate increments that version no by one automatically . In hibernate mapping file, add an element called version soon after id element.
No. Hibernate doesn't allow to change the primary key.
update Update method in the hibernate is used for updating the object using identifier. If the identifier is missing or doesn't exist, it will throw exception. saveOrUpdate This method calls save() or update() based on the operation.
Hibernate Optimistic Locking can be bypassed using hibernate Session (http://docs.jboss.org/hibernate/orm/5.0/javadocs/org/hibernate/Session.html) replicate(...) method.
Example of code which does not increment version:
//Detaching to prevent hibernate to spot dirty fields.
//Otherwise if entity exists in hibernate session replication will be skipped
//and on flush entity will be updated with version increment.
em.detach(entityDb);
someTimeConsumingProcessingOfEntityFields(entityDb);
//Telling hibernate to save without any version modifications.
//Update hapends only if no newer version exists.
//Executes additional query DB to get current version of entity.
hibernateSession.replicate(entity, ReplicationMode.LATEST_VERSION);
I think this solution is better than native SQL update, because:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With