发锁事务重试机制(JPA高并发下的乐观锁异常)总结,以及中间遇到各种问题和解决方案

接入ping++支付,账户余额的数据安全问题,使用jpa乐观锁+AOP重试机制

乐观锁:
<span style="white-space:pre">	</span>model实体类加version字段
<span style="white-space:pre">	</span>private Integer version=0;   //jpa乐观锁
	
	@Version
	@Column(name = "version")
	public Integer getVersion() {
		return version;
	}
	public void setVersion(Integer version) {
		this.version = version;
	}	

---修改实体时,
<span style="white-space:pre">		</span>tradeBAccount.setVersion(tradeBAccount.getVersion()+1);//乐观锁
<span style="white-space:pre">		</span>tradeBAccountDao.save(tradeBAccount);







参考:

并发锁事务重试机制(JPA高并发下的乐观锁异常)

 

 

        我的博文中,有一篇短文Java结合Junit做并发测试用例,是介绍JPA在高并发下,多个Service方法更新

同一个记录;在异常信息中有StaleObjectStateException和ObjectOptimisticLockingFailureException异常信

息。有些业务这种靠JPA维护的版本信息是可行的,如果两个不同用户同事(高并发)购买一件马丁靴鞋子,最后会更新该马丁靴在库数量,如果没有重试机制,肯定只有一个用户购买失败;可能这没有什么,用户再次提交购买就ok了;可是作为事逼可能成就人生的工程师,你一定不能容忍,于是有了重试机制。

 

1:解决方案

     定义Aspectj拦截器,指定方法发生乐观锁异常时,进行重试。

 

2:show coding.

 

(1) 因为不是所有方法发生乐观锁异常都是需要重试机制的,所以需要先定义切面接口定义IsTryAgain

Java代码   收藏代码
  1. /** 
  2.  * 自定义尝试切面接口 
  3.  */  
  4. @Retention(RetentionPolicy.RUNTIME)  
  5. public @interface IsTryAgain {  
  6.     // marker annotation  
  7. }  

 (2)Service接口方法加上切面接口定义

 

Java代码   收藏代码
  1. /** 
  2.  * 并发乐观锁需要重试的方法 
  3.  */  
  4. @IsTryAgain  
  5. boolean TryAgainMethod() throws Exception;  

 

(3)定义Aspectj切面拦截器

 

定义重试切面方法,是为了发生乐观锁异常时在一个全新的事务里提交上一次的操作,直到达到重试上限;因此切面实现 org.springframework.core.Ordered 接口,这样我们就可以把切面的优先级设定为高于事务通知 。

 

Java代码   收藏代码
  1. @Aspect  
  2. public class SystemArchitecture {  
  3.       
  4.     @Pointcut("execution(* myapp..service..*(..))")  
  5.     public void businessService() {  
  6.     }  
  7.       
  8. }  
 

 

 

 

Java代码   收藏代码
  1. @Aspect   
  2. class ConcurrentOperationExecutor implements Ordered {  
  3.      
  4.    private static final int DEFAULT_MAX_RETRIES = 2;  
  5.   
  6.    private int maxRetries = DEFAULT_MAX_RETRIES;  
  7.    private int order = 1;  
  8.   
  9.    public void setMaxRetries(int maxRetries) {  
  10.       this.maxRetries = maxRetries;  
  11.    }  
  12.      
  13.    public int getOrder() {  
  14.       return this.order;  
  15.    }  
  16.      
  17.    @Around("myapp.SystemArchitecture.businessService()")  
  18.    public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {   
  19.       int numAttempts = 0;  
  20.       PessimisticLockingFailureException lockFailureException;  
  21.       do {  
  22.          numAttempts++;  
  23.          try {   
  24.             return pjp.proceed();  
  25.          }  
  26.          catch(PessimisticLockingFailureException ex) {  
  27.             lockFailureException = ex;  
  28.          }  
  29.       }while(numAttempts <= this.maxRetries);  
  30.   
  31.         
  32.       throw lockFailureException;  
  33.    }  
  34.   
  35. }  
 

 3:更多

AOP知识,Spring AOP和Aspectj的知识。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值