添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
唠叨的火车  ·  java中文排序-掘金·  1 年前    · 
着急的黄瓜  ·  how to read json ...·  1 年前    · 

项目持久层框架使用spring-data-jpa,jpa实现采用hibernate。实体使用乐观锁的方式加锁,也就是添加如下字段。

    @Version
    private Long version;

最近发现在日志中偶尔报org.springframework.orm.ObjectOptimisticLockingFailureException: Object of class xxx optimistic locking failed异常。底层异常信息是hibernate抛出的org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction 。排查后发现是jpa并发更新同一个实体引起的。具体流程如下(以实体user1为例)

事务A 事务B 实体版本号version 说明
加载实体user1 加载实体user1 1 这里谁前谁后没关系
修改属性:user1.name=张三 修改属性user1.name=李四 这里谁先修改谁后修改没关系
save(user1) 2 检查版本号发现没变化,修改为2
save(user1) 检查版本号,发现自己的版本号1和实际的版本号2不匹配,判定已经被其他事务修改(事务B),则本次更新失败,抛出如上异常。

思考后有如下解决方案:

  1. 不通过jpa的实体更新方式,通过原生sql更新语句进行更新,缺点就是舍弃了jpa的对象管理方式。
  2. 通过悲观锁(for update),使事务顺序执行。缺点就是相比乐观锁降低了并发性,也需要写sql或者额外加jpa注解的方式,不够方便。
  3. 最后一种也是最终项目采用的方案,通过AOP统一拦截这种异常并进行一定次数的重试,spring官方文档在讲AOP的时候也拿这种方式举例,如下:
@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;

其中的order(1)表面此拦截在事务拦截的上层,否则会报错。

不过后来想想这种方式如果在重试模块不支持重试的情况下,就会存在问题。这就要看具体业务是什么样,设计不同的处理方式了。

项目持久层框架使用spring-data-jpa,jpa实现采用hibernate。实体使用乐观锁的方式加锁,也就是添加如下字段。 @Version private Long version;最近发现在日志中偶尔报org.springframework.orm.ObjectOptimisticLockingFailureException: Object of cla...
一、问题描述 新开发的系统,往往可能需要将旧版的系统中的历史数据,用脚本的方式在新系统中跑一遍业务流程,其实可能是用Java代码自动调用一些业务流程接口。 在执行过程中发现报错: 2021-01-27 19:32:46.300 [http-nio-5090-exec-4] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet]:182 - Servlet.service() for servlet [dispatcherServlet] in context with path
主要解决方案是在捕捉异常的时候使用递归方法对乐观锁重试 spamMessageFeeReceipt=genSpamMessageFeeReceipt(jsonObject,distribute); }catch (Exception e){ if(e instanceof ObjectOptimisticLockingFailureException){ spamMessageFeeReceipt=genSpamMessageFeeReceipt(jsonObjec
optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was u...
原因:就是要修改的实体的version和数据库中的version对不上。hibernate就会认为别人已经并发修改了数据。 解决办法:将数据库中的version从前端回传回来。如果version和数据库一致,还是经常出现这个问题,可以考虑使用悲观锁。 乐观锁:给数据加一个版本, 每一操作数据就更新版本,不会上锁,但是在更新的时候你会判断这期间有没有人去更新这个数据 悲观锁:给数据加了一把锁 ,同事务只能一个线程进行操作,使用完了锁释放, 没释放前后面想要操作的人就得排队 ,效率低,但是很安全 2 问题描述
主要解决方案是在捕捉异常的时候使用递归方法对乐观锁重试 public void optimisticLockingFailureSave(User user, RefundLog refundLog, OrderLog order) { try { if (user != null) {              //更新前要version要和数...
        我的博文中,有一篇短文Java结合Junit做并发测试用例,是介绍JPA在高并发下,多个Service方法更新 同一个记录;在异常信息中有StaleObjectStateExceptionObjectOptimisticLockingFailureException异常信 息。有些业务这种靠JPA维护的版本信息是可行的,如果两个不同用户同事(高并发)购买一件马丁靴鞋...
spring-boot-starter-data-jpa标红通常是由于以下几个原因导致的: 1. 缺少依赖:确保在项目的pom.xml文件中添加了spring-boot-starter-data-jpa的依赖项,并且版本号正确。如果依赖项未正确添加或版本号错误,IDE可能会显示标红。 2. 项目配置错误:检查项目的配置文件(如application.properties或application.yml)是否正确设置了与spring-boot-starter-data-jpa相关的配置项。确保数据库连接信息、实体类扫描路径等配置正确无误。 3. 编译错误:如果在代码中存在语法错误或其他编译错误,IDE会显示标红。请检查代码中是否存在错误,并进行相应的修正。 4. 依赖冲突:如果项目中存在多个不兼容的依赖项或版本冲突,可能会导致标红。请检查项目的依赖项,并确保它们之间的兼容性和版本一致性。 请根据上述原因逐一排查,找出导致标红的具体原因并进行相应的修正,以解决spring-boot-starter-data-jpa标红的问题。 remote: You are not allowed to download code from this project. 13fatal: unable to access ‘http://gi postgresql发生死锁,org.postgresql.util.PSQLException: ERROR: deadlock detected ,Process 17662 waits for remote: You are not allowed to download code from this project. 13fatal: unable to access ‘http://gi 使用antd日期组件的时候报错Invalid hook call