Joh*_*y19 23 java spring hibernate jpa transactions
我正在玩Spring和JPA/Hibernate,我对在表中递增计数器的正确方法感到困惑.
我的REST API需要根据用户操作递增和递减数据库中的某些值(在下面的示例中,喜欢或不喜欢标记会使计数器在Tag表中递增或递减1)
tagRepository是一个JpaRepository(Spring-data),我已经像这样配置了事务
<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);
}
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的那样.save(),在能够测试并发场景之前,我已经在增量JUST上进行了20秒的睡眠.
初始标签计数器= 10;
1)用户调用increaseTag并且代码命中睡眠,因此entity = 11的值和DB中的值仍为10
2)用户调用decreaseTag并遍历所有代码.值是数据库现在= 9
3)睡眠结束并使用计数为11的实体命中.save然后命中.save()
当我检查数据库时,该标签的值现在等于11 ..实际上(至少我希望实现)它将等于10
这种行为是否正常?或者@Transactional注释不做是有效的吗?
Vla*_*cea 52
最简单的解决方案是将并发性委托给您的数据库,并简单地依赖于当前修改的行上的数据库隔离级别锁定:
增量就像这样简单:
UPDATE Tag t set t.count = t.count + 1 WHERE t.id = :id;
Run Code Online (Sandbox Code Playgroud)
并且减量查询是:
UPDATE Tag t set t.count = t.count - 1 WHERE t.id = :id;
Run Code Online (Sandbox Code Playgroud)
UPDATE查询在当前事务提交之前锁定已修改的行,防止其他事务修改同一行(只要您不使用READ_UNCOMMITTED).
| 归档时间: |
|
| 查看次数: |
17631 次 |
| 最近记录: |