spring-data-jpa appear ObjectOptimisticLockingFailureException Solutions

Item persistence framework using spring-data-jpa, jpa achieved using hibernate. Entity way to use optimistic locking lock, that is, add the following fields.

    @Version
    private Long version;

 

Recently discovered in the log occasionally reported org.springframework.orm.ObjectOptimisticLockingFailureException: Object of class xxx optimistic locking failed exception. Hibernate underlying abnormality information is thrown org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction. After investigation found jpa concurrent updates to the same entity caused. Specific procedures are as follows (In Case entity user1)

A transaction Transaction B Entity version number version Explanation
Load entity user1 Load entity user1 1 Here it does not matter who the former who
Modify the properties: user1.name = Zhang Modify the properties user1.name = Doe   After this modification does not matter who is who should modify
  save(user1) 2 Check the version number found no changes, modifications of 2
save(user1)     Check the version number, the version number found their actual version numbers 1 and 2 do not match, the determination has been modified by other transactions (transaction B), then this update fails, thrown as an exception.

 

After thinking the following solutions:

  1. Jpa entity does not update by the way, is updated by the native sql update statement, the disadvantage is discarded objects jpa of management.
  2. By pessimistic lock (for update), the transaction execution order. The disadvantage is reduced compared to the optimistic locking concurrency, also need to write sql or extra jpa annotated way, is not convenient enough.
  3. The last and final program adopted by the project, through a unified AOP intercept this anomaly and make a certain number of retries, spring also get official documents in this way, for example, when talking about AOP, as follows:
@Aspect
@Component
@Order(1)
public class OptimisticLockInterceptor {

    @Pointcut("within(com.test.apis..*)")
    public void retryPointCut() {
    }

    @Around("retryPointCut()")
    public Object test(ProceedingJoinPoint pjp) throws Throwable {
        for (int i = 0; i <= 4; i++) {
            try {
                return pjp.proceed();
            } catch (OptimisticLockingFailureException ex) {
                if (i > 3) {
                    throw ex;
                }
            }
        }
        return null;
    }
}

Where the order (1) to intercept the upper surface of this transaction interception, otherwise it will error.

But then think about it this way, if the retry retry module does not support, it will be problematic. That depends on what kind of specific business is to design a different approach.

Released six original articles · won praise 1 · views 8543

Guess you like

Origin blog.csdn.net/guangmingguangming/article/details/104584053