loading

Spring Boot - @Transactional 和 synchronized 不能在一个方法中使用!

@Transactional 和锁一起用会出现一些问题,具体请看 Spring Boot 锁

tip:[start]

@Transactional 是 Spring AOP 切入编程的一种,切入点有三种基本的通知类型,如 @Before@After@Around,因此,事务开启在方法执行之前,事务提交在方法执行结束。但是,方法上锁和释放锁都在方法执行时,所以,在下一个线程进入之后,事务可能没有提交,数据库数据也没有更新,下一个线程读取的数据就有问题。

tip:[end]

图1 - 出现的问题

如图1所示,红色是线程1,黄色是线程2。线程1执行,一旦释放锁,线程2就会立马执行。但是,此时的线程1释放锁之后还没提交事务,数据库数据也未更新,线程2因锁释放也执行,导致线程2读取数据库的数据不是最新的。

而且 Idea 也会标一个黄色波浪线提示你。因此,可以新建一个类,专门调用 Mapper 做事务,也就是改变顺序。

file:[DiscussionService.java]
@Service
public class DiscussionService implements IDiscussionService {
    // ......
    @Override
    public synchronized int upgradeArticle(ArticleModel model, DiscussionCriteria criteria) {
        return transactionalWrapper.doUpgradeArticle(model, criteria);
    }
}

@AllArgsConstructor
class TransactionalWrapper {
    // ......
    @Transactional
    public int doUpgradeArticle(ArticleModel model, DiscussionCriteria criteria) {
        try {
            // ...
            Integer affectRows = discussionMapper.upgradeArticle(model);
            return affectRows > 0 ? 1 : 0;
        } catch (Exception e) {
            throw new JdbcErrorException(e);
        }
    }

}
posted @ 2023-10-31 23:50  Himmelbleu  阅读(4)  评论(0编辑  收藏  举报