2017-02-21 68 views
-1

我現在面臨一個問題,奇異...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是正確真實的。

爲什麼會發生這種情況?

回答

0

發生這種情況是因爲您正在使用update語句直接更新數據庫。在這種情況下,Hibernate不會自動更新已經加載的實體。如果您在呼叫dao.updateInterruttore後重新加載實體,則應該獲得更新的數據。

0

兩個註釋:

1)您正在使用查詢來應用更新。在這種情況下,Hibernate不會更新會話中的實體。除非您更新實體本身並致電session.save(interruttore),否則實體將不會更新。 (但更新顯示在數據庫中。)此外,我不明白爲什麼你只是不更新​​實體並通過session.save()進行保存。

2)您正在使用@Transactional註釋服務方法。 (假設是Spring註解)如果你使用JTA,你的tx.commit()將不起作用。但是一旦這個方法完成了,你的交易就被承諾了。 (或者在方法拋出異常時回滾)如果你不使用JTA,那麼就像你在做的那樣,拋棄@Transactional並且在你的DAO方法中管理事務。但這被認爲是不好的做法。

+0

我的問題是,我有多個併發調用方法,但只有1(第一個)必須調用'pushButton(rele)'調用並更新Interruttore,所以其他人應該看到'interruttore.isStato ()'並且不要調用按下功能。我做了幾次嘗試,並以這種方式,我發現它的工作(或多或少)。我使用的是Spring'@Transactional',通常我只是使用它們的setter方法更新實體... – besmart

+0

這聽起來是你將業務併發與數據庫併發混合在一起。事實上,你在事務中調用Thread.sleep是一個非常糟糕的跡象。您應該重新設計代碼,以便與Hibernate會話和數據庫進行交互的時間非常少,並在別處管理應用程序併發。數據庫併發性基於事務,而不是用戶。 – raminr

相關問題