How can I achieve the equivalent of this code:
tx.begin();
Widget w = em.find(Widget.class, 1L, LockModeType.PESSIMISTIC_WRITE);
w.decrementBy(4);
em.flush()
If you are able to use Spring Data 1.6 or greater than ignore this answer and refer to Oliver's answer.
The Spring Data pessimistic @Lock annotations only apply (as you pointed out) to queries. There are not annotations I know of which can affect an entire transaction. You can either create a findByOnePessimistic method which calls findByOne with a pessimistic lock or you can change findByOne to always obtain a pessimistic lock.
If you wanted to implement your own solution you probably could. Under the hood the @Lock annotation is processed by LockModePopulatingMethodIntercceptor which does the following:
TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);
You could create some static lock manager which had a ThreadLocal member variable and then have an aspect wrapped around every method in every repository which called bindResource with the lock mode set in the ThreadLocal. This would allow you to set the lock mode on a per-thread basis. You could then create your own @MethodLockMode annotation which would wrap the method in an aspect which sets the thread-specific lock mode before running the method and clears it after running the method.