4

我想實現Rest API的註冊控制器。我已經閱讀了很多關於@Transactional的地方。 (不是在DAO級別,而是在可能協調的服務)。在我的用例中,我不僅需要服務,而且還希望使用相同的事務進行hibernate驗證。休眠驗證和彈簧控制器的一個事務

這是控制器的代碼:

@Autowired 
private UserService userService; 

@RequestMapping(method = RequestMethod.GET) 
@ResponseBody 
@Transactional 
public DefaultResponse register(@Valid RegisterIO registerIO, BindingResult errors) { 
    DefaultResponse result = new DefaultResponse(); 

    if (errors.hasErrors()) { 
     result.addErrors(errors); 
    } else { 
     userService.register(registerIO); 
    } 

    return result; 
} 

我寫了定製contraint註解,這驗證了參數registerIO的屬性。這兩個驗證器和userService.register(registerIO);訪問數據庫(檢查電子郵件地址是否已被使用)。

因此我希望這兩種方法都使用相同的Hibernate會話和事務。

這種做法的結果是以下異常:

org.hibernate.HibernateException: No Session found for current thread 
org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97) 
org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:941) 

的問題是@Transactional註解。當我將這個註解放在所有可以找到的數據庫的方法中時,只有兩個事務是startet。我懷疑,當我將它放在註冊方法中時,在@Transactional啓動此方法的事務之前執行hibernate驗證。

我開發了以下功能解決方法,但我不滿意。這個代碼不使用@Valid註解,但是調用驗證本身:

@RequestMapping(method = RequestMethod.GET) 
@ResponseBody 
@Transactional 
public DefaultResponse register(RegisterIO registerIO, BindingResult errors) { 
    DefaultResponse result = new DefaultResponse(); 

    ValidatorFactory vf = Validation.buildDefaultValidatorFactory(); 
    Validator validator = vf.getValidator(); 
    Set<ConstraintViolation<RegisterIO>> valResult = validator.validate(registerIO); 

我試着總結一下我的問題: 使用Spring MVC和Hibernate驗證與@Valid和@Transactional在一起,怎麼可能將整個請求封裝到一個事務中?

謝謝:)

+0

您使用的是JSR 330驗證嗎? –

+0

JSR 330:Java的依賴注入:我使用Spring進行依賴注入。 @Autowire在這種情況下工作正常。我不確定你的意思是JSR 303:Bean驗證:這裏我使用Hibernate-Validator 4.3.1實現 – Sebastian

+0

回答這個問題。 Hibernate Validator是Bean Validation(JSR 330)規範的參考實現。 – Hardy

回答

1

你的解決方法可以通過使用一個單一的驗證,並注入其INTP控制器得到改進。您是否嘗試過:

@Autowired 
private Validator validator; 

這樣您可以跳過在每個請求上創建驗證器的開銷。 你也應該注意比賽條件。在檢查數據庫時,是否存在給定的電子郵件,另一個請求可以創建此記錄,以便在插入數據時仍然會發生異常。

+0

解決方法改進工作正常。哦,我沒有想過這種特殊的競爭條件。我的想法是:在一個事務中合併驗證和控制器執行將解決所有問題,如「丟失更新」或至少會拋出異常/回滾。在這種情況下檢查未使用的電子郵件不會產生讀/寫衝突。也許我應該問一下如何在另一個問題上做這件事,並做更多的閱讀。謝謝 :) – Sebastian