Spring Data Jpa是findOne方法返回被管实体吗?

时间:2017-02-14 10:14:37

标签: java spring hibernate jpa spring-data-jpa

我有一个提供 POST 请求(文件上传)的控制器,但实际上提供了更新。逻辑很简单:   - 通过id查找对象   - 如果我们没有这样的对象返回BAD_REQUEST   - 否则更新找到的对象并返回更新为 ResponseEntity

@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) {...}

}

1 ,我们更新检索(最后由CrudRepository#findOne)实体并更新并保存到DB值中。

我的问题是:我们可以改变方法参数并给出这个变异的结果,还是我们应该在方法内部制作克隆参数,然后改变它然后给出结果?

就jpa / hibernate而言:CrudRepository#findOne是否为我们提供了managed/attached实体?我个人认为 - 不,原因调用它的方法没有标记@Transactional我们可以克隆它,调用CrudRepository#save来提供更新

1 个答案:

答案 0 :(得分:2)

Spring data-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) {...}

如果实体不存在,则optional为空。如果实体存在,则optional在更新后包含实体。