乐观锁:
model实体类加version字段
@JsonProperty("_version")
@Column(name = "version", nullable = false)
@Version
private Long version = 0L;
问题场景
先在库里查询出该实体,转化为持久态,在这时库里的该数据被修改了,并且version发生变更,此时持久态实体进行save操作,会触发乐观锁异常。
1:解决方案
定义Aspectj拦截器,指定方法发生乐观锁异常时,进行重试。
2:show coding.
(1) 因为不是所有方法发生乐观锁异常都是需要重试机制的,所以需要先定义切面接口定义IsTryAgain
/**
* 自定义尝试切面接口
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface IsTryAgain {
// marker annotation
}
(2)Service接口方法加上切面接口定义
/**
* 并发乐观锁需要重试的方法
*/
@IsTryAgain
boolean TryAgainMethod() throws Exception;
(3)定义Aspectj切面拦截器
定义重试切面方法,是为了发生乐观锁异常时在一个全新的事务里提交上一次的操作,直到达到重试上限;因此切面实现 org.springframework.core.Ordered 接口,这样我们就可以把切面的优先级设定为高于事务通知 。
@Aspect
public class SystemArchitecture {
@Pointcut("execution(* myapp..service..*(..))")
public void businessService() {
}
}
@Aspect
class ConcurrentOperationExecutor implements Ordered {
private static final int DEFAULT_MAX_RETRIES = 2;
private int maxRetries = DEFAULT_MAX_RETRIES;
private int order = 1;
public void setMaxRetries(int maxRetries) {
this.maxRetries = maxRetries;
}
public int getOrder() {
return this.order;
}
@Around("myapp.SystemArchitecture.businessService()")
public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
int numAttempts = 0;
PessimisticLockingFailureException lockFailureException;
do {
numAttempts++;
try {
return pjp.proceed();
}
catch(PessimisticLockingFailureException ex) {
lockFailureException = ex;
}
}while(numAttempts <= this.maxRetries);
throw lockFailureException;
}
}
3:更多
AOP知识,Spring AOP和Aspectj的知识。
来源:https://blog.csdn.net/weixin_36795183/article/details/100539812