2017-02-14 84 views
1

我有一個控制器,服務POST請求(文件上傳),但實際上提供更新。邏輯很簡單: - 通過ID 找到對象 - 如果我們沒有這樣的對象返回BAD_REQUEST - 否則更新發現對象,並返回更新ResponseEntitySpring Data Jpa findOne方法是否返回被管實體?

@PostMapping("/{id}") 
public ResponseEntity<?> post(@PathVariable("id") long id, 
     @RequestParam("file") MultipartFile file) { 
    //this is not @Transactional method 
    Optional<Job> jobOptional = jobService.getJobById(id); 
    return jobOptional 
      .map(
       job -> 
        getSuccessfulResponse(
         //this is @Transactional 
         jobService.update(job, file))) //1 
      .orElse(
       getBadRequestResponse(
        getJobNotFoundByIdMessage(id))); 

} 
[...] 
@Service 
public class JobService { 

    @Transactional 
    public Job update(Job job, MultipartFile file) {...} 

} 

在我們更新(最後由CrudRepository#findOne)實體檢索並更新並保存爲DB值。

我的問題是:我們可以改變方法參數並返回這個突變的結果,或者我們應該在方法內部創建clone參數,然後改變它然後返回結果嗎?

就jpa/hibernate而言:CrudRepository#findOne給我們一個managed/attached實體嗎?我個人認爲 - 不,導致調用它的方法沒有標記@Transactional,我們可以克隆它,調用CrudRepository#save來提供更新

回答

1

Spring數據jpa存儲庫方法被@Transactional包裝。 爲了讓您的實體作爲託管傳遞回來,您需要使用@Transactional來包裝調用存儲庫方法的公共方法。

因此,交易將處於更高的水平。

例如

@Transactional 
public void makeChanges(Long id) { 

    User user = userRepository.findOne(id); 
    user.setName("Someone"); 
} 

在您的變更應自用戶節省了交易的到底是一個管理實體。

您可以更改您的服務以傳回可選實體是否存在。例如

@Transactional public Optional<Job> update(Job job, MultipartFile file) {...} 

如果實體不存在,則可選爲空。如果實體存在,則可選包含更新後的實體。

+1

它已經包裝,因爲我提到的問題。我不確定。兩次檢索同一個實體是個好主意。感謝您使用@Transactional'來封裝Spring data-jpa存儲庫方法。我不知道。實際上它是'@Transactional(readOnly = true)' –

+0

您可以更改您的服務以傳回可選實體是否存在。例如 @Transactional public可選更新(作業作業,MultipartFile文件){...} 如果實體不存在,則可選爲空。如果實體存在,則可選包含更新後的實體。 – gkatzioura

+0

非常好的一點。它解決了我的情況。謝謝! –

相關問題