Spring, JPA e Hibernate: cómo incrementar un contador sin problemas de concurrencia
Estoy jugando un poco con Spring y JPA / Hibernate y estoy un poco confundido sobre la forma correcta de incrementar un contador en una mesa.
Mi API REST necesita aumentar y disminuir algún valor en la base de datos dependiendo de la acción del usuario (en el ejemplo siguiente, si le gusta o no una etiqueta, el contador aumentará o disminuirá en uno en la Tabla de etiquetas)
tagRepository
es unJpaRepository
(Spring-data) y he configurado la transacción de esta manera
<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);
}
}
Como puede ver, he puesto un sueño de 20 segundos en incrementos JUSTO antes del.save()
para poder probar un escenario de concurrencia.
contador de etiqueta inicial = 10;
1) Un usuario llama al aumento de etiqueta y el código llega al modo de suspensión, por lo que el valor de la entidad = 11 y el valor en la base de datos sigue siendo 10
2) un usuario llama a la etiqueta disminuir y revisa todo el código. el valor es la base de datos es ahora = 9
3) El sueño finaliza y golpea el .save con la entidad contando 11 y luego golpea .save ()
Cuando reviso la base de datos, el valor de esa etiqueta ahora es igual a 11 .. cuando en realidad (al menos lo que me gustaría lograr) sería igual a 10
¿Es este comportamiento normal? O la@Transactional
anotación no está haciendo es trabajo?