2016-03-26 88 views
1

我非常想知道爲什麼當我嘗試使用@Scheduled方法時我的更新沒有提交。
這是我的方案的簡化:Spring @Transactional只有在調用者也是@Transactional時纔有效

@Service 
public class UserService { 

    @Transactional 
    public void updateUser(User user){ 
     user.setName("Doe"); 
    } 
} 

這項服務是由兩個位置叫:

@RestController 
@RequestMapping(value = "/users") 
public class UserController { 

    @Autowired 
    private UserService userService; 
    @Autowired 
    private UserRepository userRepository; 

    @ResponseStatus(HttpStatus.OK) 
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT) 
    public void getAvailableIssuers(@PathVariable("id") String id){ 
     User user = userRepository.findOne(id); 
     userService.updateUser(user); 
    } 
} 

和服務,使用@Scheduled方法:

@Component 
class InternalService { 

    @Autowired 
    private UserService userService; 

    @Autowired 
    private UserRepository userRepository; 

    @Scheduled(fixedRate=1000) 
    public void updateUser(){ 
     User user = userRepository.findOne(1L); 
     userService.updateUser(user); 
    } 
} 

我的問題是當我嘗試更新用戶通過InternalService用戶永遠不會更新 - 但它正在更新pe通過RestController完美無瑕。當我爲預定方法添加註釋時(即使使用readOnly = true),它也可以工作。

我從spring瞭解關於交易的文檔,但我仍然不明白爲什麼它不起作用。我使用debuger進行了檢查,userService採用Spring Proxy的形式。

有人可以幫我解釋一下嗎?

回答

0

問題是您的操作不受限於該服務方法:在這兩種情況下,都是從調用方法中的存儲庫中檢索對象。您的交易必須覆蓋整個數據庫操作集合。至於爲什麼你的控制器實際上是工作,我不能肯定只有這個信息,但我猜你正在使用OpenEntityManagerInView並獲得免費的交易界限。

+0

好的。說得通。 Spring引導默認使用'OpenEntityManagerInView'(spring.jpa.open-in-view屬性),區別在於此。 – mvlupan

+0

將「Transactional」標註的預定方法是否合理?或者重構一個更好的主意? – mvlupan

+0

@mvlupan要麼是一個可行的方法。這取決於你的用例的具體情況。如果「更新」真的很簡單,那麼交易似乎並不在這一層,因此我會將邊界向上移動。 – chrylis