I'm using Spring Boot (1.4.4.REALEASE) with Spring Data in order to manage a MySql Database. I've got the following case:
RevisionService
.RevisionService
saves the revision and calls the EquipmentService
to update the equipment status.I've tried some options but don't achieve to get the updated status for the equipment. The updateEquipmentStatus
method keeps writing the previous status for the equipment (not considering the current revision being stored in the transaction). The code is written this way:
RevisionService
@Service
public class RevisionService{
@org.springframework.transaction.annotation.Transactional
public Long saveRevision(Revision rev){
//save the revision using JPA-Hibernate
repo.save(rev);
equipmentService.updateEquipmentStatus(idEquipment);
}
}
EquipmentService
@Service
public class EquipmentService{
@org.springframework.transaction.annotation.Transactional
public Long updateEquipmentStatus(Long idEquipment){
repo.updateEquipmentStatus(idEquipment);
}
}
EquipmentRepo
@Repository
public interface EquipmentRepo extends CrudRepository<Equipment, Long> {
@Modifying
@Procedure(name = "pupdate_equipment_status")
void updateEquipmentStatus(@Param("id_param") Long idEquipment);
}
As far as I understand, as both methods are annotated with Spring's transactional, the updateEquipmentStatus
method should be executed in the scope of the current transaction. I've also tried with different options for the @Transactional
annotation from updateEquipmentStatus
, such as @Transactional(isolation=Isolation.READ_UNCOMMITTED)
(which shouldn't be required, because I'm using the same transaction) and @Transactional(propagation=Propagation.REQUIRES_NEW)
, but keeps not considering the current status. That's how my stored procedure is saved into the MySql DB:
CREATE DEFINER=`root`@`localhost` PROCEDURE `pupdate_equipment_status`(IN `id_param` INT)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
COMMENT ''
BEGIN
/*Performs the update considering tequipment and trevision*/
/*to calculate the equipment status, no transaction is managed here*/
END
I also want to clarify that if I execute some modification in the equipment itself (which affects only tequipment), the status is being properly updated. InnoDb is the engine being used for all the tables.
UPDATE
Just changed the repo method to use a nativeQuery instead and the same problem keeps happening, so the Db procedure being involved should be discarded:
@Modifying
@Query(nativeQuery = true, value= "update tequipment set equipment_status = (CASE WHEN (...))")
void updateEquipmentStatus(@Param("id_param") Long idEquipment);
UPDATE2
Having done more tests and added a log with TransactionSynchronizationManager.getCurrentTransactionName()
in the methods, that's the concrete issue:
establishEquipmentStatus
, because the current transaction name changes, but the native query doesn't have the latest values (because of the transaction before not being commited?). Also tried removing @Transactional
from establishEquipmentStatus
so the same transaction is used, but the issue keeps happening.Adding the following code fixes it (programatically flushing the transaction state to the Database):
@Service
public class EquipmentService{
@PersistenceContext
private EntityManager entityManager;
@org.springframework.transaction.annotation.Transactional
public Long updateEquipmentStatus(Long idEquipment){
entityManager.flush();
repo.updateEquipmentStatus(idEquipment);
}
}
Still it would be great to find a declarative way to do it..
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With