I have two classes say Foo and Bar mapped as @OneToOne (bidirectional) using Hibernate (3.6.1 final) with JPA (2.0) like -
@Entity
public class Foo{
@Id
private Long id;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "foo")
private Bar bar;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "foo")
private Qux qux;
@Version
private int version;
// getters and setters omitted
}
@Entity
public class Bar{
@Id
private Long id;
@OneToOne
@JoinColumn(name = "foo_id", nullable = false)
private Foo foo;
// getters and setters omitted
}
@Entity
public class Qux {
@Id
private Long id;
@OneToOne
@JoinColumn(name = "foo_id", nullable = false)
private Foo foo;
// getters and setters omitted
}
Note that - Bar and Qux doesn't have @Version
column
If we update Bar then hibernate will not increment the version of Foo and same for Qux. But our business logic needs - if someone updates Bar in the Foo and other thread is trying to update the Qux of the same Foo but doesn't have updated Bar and vice versa then such updates should fail.
Since hibernate doesn't update the version property of Foo if we update the Bar, we decided to update the version of Foo manually (I know it's pretty weird and not recommended) if we update the Bar and Qux.
It works perfectly fine.. but I'm worry about some corner cases in concurrency which may fail this or will have unintended behavior.
Is it safe to do this kind of tweak with version for this purpose? OR is there any other better alternative to this (I've already tried optimistic/pessimistic force increament)
Check if your Hibernate JAR has a META-INF/MANIFEST. MF with the version in it. It looks like the JBoss folks were using Ant at this time and the Manifest doesn't provide the version. Dig the JBoss Embedded SVN to find out what they're doing exactly.
If the data is read by two threads at the same time, and both try to update the same row with different values, Hibernate uses the @Version field to check if the row is already updated. Before committing, each transaction verifies that no other transaction has modified its data.
We can update an object in hibernate by calling the update() method, provided by the org. hibernate. Session. Though the update() method is used to update an object, there are two different ways to use update() method.
We can update an object in hibernate by calling the update () method, provided by the org.hibernate.Session. Though the update () method is used to update an object, there are two different ways to use update () method. Without loading an object from the database Loading an object from the database
Hibernate generates an UPDATE statement that only increments the version while leaving all the other columns unchanged (their values are identical to the ones that were previously loaded from the database): If you want to force an entity version change, you need to use either OPTIMISTIC_FORCE_INCREMENT or PESSIMISTIC_FORCE_INCREMENT.
The @Version annotation allows Hibernate to activate the optimistic locking mechanism whenever executing an UPDATE or a DELETE statement against the entity in question.
This is an upgraded version of Hibernate ORM 5.2 and Hibernate Search 5.9. Compatible with Java 8 and the latest version, JPA 2.1 and Hibernate ORM 5.2, Hibernate search 5.9. Hibernate OGM is also compatible with this version.
The correct way to force version update is the following:
em.lock(entity, LockModeType.OPTIMISTIC_FORCE_INCREMENT);
It's intended to be used in such cases.
Other methods of EntityManager
that take LockModeType
can be used as well.
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