Spring、JPA 和 Hibernate - 如何在没有并发问题的情况下递增计数器
2022-09-01 05:48:10
我正在玩Spring和JPA / Hibernate,我对在表格中增加计数器的正确方法有点困惑。
我的 REST API 需要根据用户操作在数据库中递增和递减某些值(在下面的示例中,喜欢或不喜欢标记将使计数器在标记表中增加或减少 1)
tagRepository
是一个(Spring-data),我已经像这样配置了事务JpaRepository
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"/>
@Controller
public class TestController {
@Autowired
TagService tagService
public void increaseTag() {
tagService.increaseTagcount();
}
public void decreaseTag() {
tagService.decreaseTagcount();
}
}
@Transactional
@Service
public class TagServiceImpl implements TagService {
public void decreaseTagcount() {
Tag tag = tagRepository.findOne(tagId);
decrement(tag)
}
public void increaseTagcount() {
Tag tag = tagRepository.findOne(tagId);
increment(tag)
}
private void increment(Tag tag) {
tag.setCount(tag.getCount() + 1);
Thread.sleep(20000);
tagRepository.save(tag);
}
private void decrement(Tag tag) {
tag.setCount(tag.getCount() - 1);
tagRepository.save(tag);
}
}
如您所见,我故意在能够测试并发方案之前以增量方式休眠 20 秒。.save()
初始标记计数器 = 10;
1) 用户调用 riseTag,代码命中睡眠,因此实体的值 = 11,DB 中的值仍为 10
2)用户调用downuceTag并遍历所有代码。该值是数据库现在 = 9
3) 睡眠完成并命中 .save,其中实体的计数为 11,然后单击 .save()
当我检查数据库时,该标记的值现在等于 11。在现实中(至少是我想实现的),它将等于10
这种行为正常吗?还是注释没有做的工作?@Transactional