我有一个提供 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
来提供更新
答案 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在更新后包含实体。