Spring,JPA和Hibernate - 如何在没有并发问题的情况下递增计数器
Spring,JPA和Hibernate - 如何在没有并发问题的情况下递增计数器
我在使用Spring和JPA/Hibernate进行一些尝试,并且对于在表中递增计数器的正确方法感到有些困惑。
我的REST API需要根据用户的操作(在下面的示例中,喜欢或不喜欢一个标签将使计数器在Tag表中递增或递减一)
tagRepository是一个JpaRepository(Spring-data)
我已经像这样配置了事务
@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);
}
}
正如您所看到的,我在递增方法的.save()
之前故意设置了20秒的睡眠时间,以便测试并发场景。
初始标签计数器= 10;
1)用户调用increaseTag并且代码进入睡眠状态,因此实体的值= 11,数据库中的值仍然为10
2)用户调用decreaseTag并通过所有代码。数据库中的值现在= 9
3)睡眠结束并且实体具有计数为11的值,然后进行.save()
当我检查数据库时,该标签的值现在等于11..而实际上(至少我想要实现的是)它应该等于10
这种行为正常吗?还是@Transactional注释没有起作用?