tag:blogger.com,1999:blog-34620758.post5537817373357570926..comments2022-10-27T03:23:18.302-07:00Comments on Fun Of Math: An Implementation of Pessimistic Locking with JPAJohn Paulhttp://www.blogger.com/profile/03099984750605700968noreply@blogger.comBlogger4125tag:blogger.com,1999:blog-34620758.post-11212065878566813002009-01-09T13:59:00.000-08:002009-01-09T13:59:00.000-08:00I just ran across this, and I think you have a mis...I just ran across this, and I think you have a misconception of FlushModeType.AUTO (the only alternative to FlushModeType.COMMIT in EJB 3.0). JPA does not require any SQL to be executed immediately when the flush mode is FlushModeType.AUTO. Far from it. It requires in that case <B>only</B> that any pending inserts, updates, and deletes <I>that could change the result of a query in the same transaction</I> be performed before that query is run. Other interactions with the database can be scheduled at the discretion of the EntityManager, at any time up to a flush or transaction commit. FlushModeType.COMMIT removes the requirement for flushing any SQL to the database before an explicit flush or transaction commit. (That can be a significant performance optimization if many entities are being queried, because dirty checks don't need to be performed before queries.)<BR/><BR/>Furthermore, the JPA spec explicitly provides that if EntityManager.lock() is implemented by taking out a DB lock, that may be deferred. The lock may be taken out as late as transaction commit time. (Java Persistence API specification, section 3.4.) Individual persistence implementations may choose to take out the lock immediately, but you depend on that behavior at your peril. The behavior of EntityManager.lock() is defined in terms of preventing dirty and non-repeatable reads from happening <I>silently</I>. It does not require them to be altogether prevented. The persistence implementation has the option to detect them after the fact and prevent the transaction from committing successfully.<BR/><BR/>If you genuinely need a pessimistic lock, then your most reliable option is to execute the appropriate SQL for that as a native query.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-34620758.post-84472382327688019072008-06-19T07:32:00.000-07:002008-06-19T07:32:00.000-07:00Actually, I think my use of the term "buggy" above...Actually, I think my use of the term "buggy" above is wrong. As long as your EntityManager is not using FlushModeType.COMMIT, the SQL should be executed immediately. Be sure to read the <A HREF="http://java.sun.com/javaee/5/docs/api/index.html?javax/persistence/package-summary.html" REL="nofollow">JPA Javadocs</A>.John Paulhttps://www.blogger.com/profile/03099984750605700968noreply@blogger.comtag:blogger.com,1999:blog-34620758.post-29225009605035524922008-06-19T07:15:00.000-07:002008-06-19T07:15:00.000-07:00One thing you can do is immediately lock the entit...One thing you can do is immediately lock the entity after you find it just like the application on my implementation does.<BR/><BR/>You can call EntityManager.find() or EntityManager.getReference() to get the entity or its reference and then EntityManager.lock(entity) to lock it. You may need to call EntityManager.flush() if the implementation is, in my opinion at least, buggy to execute the SQL UPDATE from the lock() call.<BR/><BR/>However, unless the implementation of the EntityManager that you are using does something similar to what my implementation does, you'll need to handle a PersistenceException from your call to lock() since another part of the application may have updated the entity between your find() or getReference() call and your lock() call. An exception will be thrown if your application has high concurrency with multiple threads or requests trying to lock the same entity simultaneously.<BR/><BR/>My experience with the JPA is only with my own partial implementation as I've integrated it into parts of an existing application. The Hibernate implementation you are using may have options for locking hints that can do true pessimistic locking in a nonstandard way. Check <A HREF="http://www.hibernate.org/5.html#A12" REL="nofollow">their documentation</A> for <A HREF="http://www.hibernate.org/hib_docs/entitymanager/reference/en/html/objectstate.html#d0e1162" REL="nofollow">more info about locking</A>.John Paulhttps://www.blogger.com/profile/03099984750605700968noreply@blogger.comtag:blogger.com,1999:blog-34620758.post-66120877239593557402008-06-18T07:18:00.000-07:002008-06-18T07:18:00.000-07:00Perhaps you can help me please. I am working on a ...Perhaps you can help me please. I am working on a program that uses JPA/Hibernate accessing SQL Server 2005. I want to do a something like a sql statement " with(holdlock, rowlock) " that you would do to avoid someone else from getting this record before I have a chance to update it. Would you use Optimistic Locking with JPA to obtain the same effect? Any ideas on how to go about doing this or references on the web on how to do this? Thanks.Unknownhttps://www.blogger.com/profile/16589178698206108235noreply@blogger.com