我们有一个Spring Boot应用程序,与现场的各种客户端链接。此应用程序具有一个控制器,从客户端调用并与数据库和物理开关交互,以打开或关闭灯。
问题在于当两个或多个客户端同时访问服务器上的API时,方法会检查灯是否打开或关闭(在数据库中)以更改其状态。如果灯是关闭的,并且同时有两个客户端调用服务,则第一个客户端打开灯并在数据库中更改状态,但第二个客户端也访问了该灯,此时数据库中的状态为关闭,但是第一个客户端已经打开了它,所以第二个客户端最终会误认为它需要将它关闭而不是打开...也许我的解释有点不太清楚,问题是:我能告诉Spring一次只访问一个控制器吗?
感谢下面的答案,我们在切换开关的方法上引入了悲观锁定,但我们仍然从客户端获得200的状态...
我们正在使用Spring Boot + Hibernate 现在该控制器具有悲观锁定异常。
问题在于当两个或多个客户端同时访问服务器上的API时,方法会检查灯是否打开或关闭(在数据库中)以更改其状态。如果灯是关闭的,并且同时有两个客户端调用服务,则第一个客户端打开灯并在数据库中更改状态,但第二个客户端也访问了该灯,此时数据库中的状态为关闭,但是第一个客户端已经打开了它,所以第二个客户端最终会误认为它需要将它关闭而不是打开...也许我的解释有点不太清楚,问题是:我能告诉Spring一次只访问一个控制器吗?
感谢下面的答案,我们在切换开关的方法上引入了悲观锁定,但我们仍然从客户端获得200的状态...
我们正在使用Spring Boot + Hibernate 现在该控制器具有悲观锁定异常。
try {
String pinName = interruttore.getPinName();
// logger.debug("Sono nel nuovo ciclo di
// gestione interruttore");
if (!interruttore.isStato()) { // solo se
// l'interruttore
// è
// spento
GpioPinDigitalOutput relePin = interruttore.getGpio()
.provisionDigitalOutputPin(RaspiPin.getPinByName(pinName));
interruttoreService.toggleSwitchNew(relePin, interruttore, lit); // accendo
interruttore.getGpio().unprovisionPin(relePin);
}
} catch (GpioPinExistsException ge) {
logger.error("Gpio già esistente");
} catch (PessimisticLockingFailureException pe){
logger.error("Pessimistic Lock conflict", pe);
return new ResponseEntity<Sensoristica>(sensoristica, HttpStatus.CONFLICT);
}
toggleSwitchNew
如下所示
@Override
@Transactional(isolation=Isolation.REPEATABLE_READ)
public void toggleSwitchNew(GpioPinDigitalOutput relePin, Interruttore interruttore, boolean on) {
Date date = new Date();
interruttore.setDateTime(new Timestamp(date.getTime()));
interruttore.setStato(on);
String log = getLogStatus(on) + interruttore.getNomeInterruttore();
logger.debug(log);
relePin.high();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
logger.error("Errore sleep ", e);
}
relePin.low();
updateInterruttore(interruttore);
illuminazioneService.createIlluminazione(interruttore, on);
}
然后我们在客户端记录请求的状态码,即使它们是并发的,它们始终会得到200