我現在面臨一個問題,奇異...Spring + Hibernate - 當事務真的被提交時?
我需要更新的實體,但我不知道什麼時候是真正更新
我的方法是
@Override
@Transactional(isolation = Isolation.SERIALIZABLE)
public void lightOn(int idInterruttore) {
Interruttore interruttore = dao.findById(idInterruttore);
String inputPin = interruttore.getInputPin();
String pinName = interruttore.getRelePin();
GpioController gpio = interruttore.getGpio();
GpioPinDigitalOutput rele = gpio.provisionDigitalOutputPin(RaspiPin.getPinByName(pinName));
try {
DateTime date = new DateTime();
Date now = date.toDate();
int i = 1;
while (getInput(inputPin, gpio) != 1) {
if(i > 1){
logger.debug(String.format("Try n %s", i));
}
pushButton(rele);
Thread.sleep(1000);
i++;
}
dao.updateInterruttore(idInterruttore, now, true);
} catch (GpioPinExistsException | InterruptedException gpe) {
logger.error("GPIO già esistente", gpe);
} finally {
gpio.unprovisionPin(rele);
}
logger.debug(String.format("After the update status should be true and it's %s",
interruttore.isStato()));
}
updateInterruttore被(我用這個表格確保在更新後調用提交...我有鎖定選項,因爲可以對此方法執行多個調用,但只有第一個必須更新
@Override
public void updateInterruttore(int idInterruttore, Date dateTime, boolean stato) {
Session session = getSession();
Transaction tx = session.beginTransaction();
String update = "update Interruttore i set i.dateTime = :dateTime, i.stato = :stato where idInterruttore = :idInterruttore";
session.createQuery(update).setTimestamp("dateTime", dateTime).setBoolean("stato", stato)
.setInteger("idInterruttore", idInterruttore).setLockOptions(LockOptions.UPGRADE).executeUpdate();
tx.commit();
}
}
嗯......當我更新日誌說我:
After the update status should be true and it's false
這種情況只有我第一次調用該方法,第二次interruttore.isStato是正確真實的。
爲什麼會發生這種情況?
我的問題是,我有多個併發調用方法,但只有1(第一個)必須調用'pushButton(rele)'調用並更新Interruttore,所以其他人應該看到'interruttore.isStato ()'並且不要調用按下功能。我做了幾次嘗試,並以這種方式,我發現它的工作(或多或少)。我使用的是Spring'@Transactional',通常我只是使用它們的setter方法更新實體... – besmart
這聽起來是你將業務併發與數據庫併發混合在一起。事實上,你在事務中調用Thread.sleep是一個非常糟糕的跡象。您應該重新設計代碼,以便與Hibernate會話和數據庫進行交互的時間非常少,並在別處管理應用程序併發。數據庫併發性基於事務,而不是用戶。 – raminr