Spring, JPA и Hibernate - как увеличить счетчик без проблем с параллелизмом
Я немного поиграюсь с Spring и JPA / Hibernate, и я немного запутался в правильном способе увеличения счетчика в таблице.
Мой REST API должен увеличивать и уменьшать какое-то значение в базе данных в зависимости от действий пользователя (в приведенном ниже примере, привязка или неприятие тега приведет к увеличению или уменьшению счетчика на единицу в таблице тегов)
tagRepository
этоJpaRepository
(Spring-data) и я настроил транзакцию следующим образом
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"/>
@Controller
public class TestController {
@Autowired
TagService tagService
public void increaseTag() {
tagService.increaseT,agcount();
}
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) Пользователь вызывает IncrementTag, и код попадает в спящий режим, поэтому значение объекта = 11, а значение в БД по-прежнему 10
2) пользователь вызываетужалую метку и просматривает весь код. значение базы данных сейчас = 9
3) Сны заканчиваются и попадают в .save с сущностью, имеющей счет 11, а затем нажимают .save ()
Когда я проверяю базу данных, значение этого тега теперь равно 11 .. тогда как в действительности (по крайней мере, то, что я хотел бы достичь), оно было бы равно 10
Это нормальное поведение? Или@Transactional
аннотация не делает это работа?