Spring Data JPA 在我不希望它更新实体时更新它
Spring Data JPA updates entity when I don't want it to
我有一种情况,我想检索数据,但在 returned 之前,我想在没有 saving/persisting 的情况下更改它。
这是我的休息控制器:
@RestController
@RequestMapping("api/drawing-releases")
@CrossOrigin("*")
public class DrawingReleaseRestController {
@Autowired
private DrawingReleaseService service;
@RequestMapping(method = RequestMethod.GET, value = "/{id}")
@JsonView(View.DrawingReleaseView.class)
public ResponseEntity<DrawingRelease> getWithId(@PathVariable int id) throws EntityNotFoundException {
return new ResponseEntity<>(service.getByID(id),HttpStatus.OK);
}
}
这是服务实现:
@Service
public class DrawingReleaseServiceImpl extends DrawingFunctions implements DrawingReleaseService {
/**
* Logging Manager
*/
private static final Logger LOGGER=LogManager.getLogger();
@Autowired
private DrawingReleaseRepository repository;
@Override
public DrawingRelease getByID(int id) throws EntityNotFoundException {
Optional<DrawingRelease> opt = repository.findById(id);
...
// manipulate the data here
...
return opt.get();
}
}
最初我在服务上有 @Transactional
注释。通过删除它而不是在 getByID
方法上使用它,我首先认为会话将按照答案 here.
所示与存储库一起打开和关闭
那没有用,我在评论中看到 "the session lasts for the entire duration of HTTP request processing." 所以,在我添加的服务中
@Autowired
private EntityManager em;
然后在 getByID
方法中我添加了
em.close();
在我进行任何更改之前。但是,我所做的任何更改仍会保留。
有什么方法可以在我的服务层中进行未保存的更改?我想我可以创建一些 POJO 来镜像实体(但不是实体),然后复制数据和 return 这些对象,但我似乎不必做那样的事情。
是的,您可以 detach
来自持久性上下文的实体:https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#detach-java.lang.Object-
你说你想获得一个实体然后更改数据然后 return 它没有实体被持久化但是恕我直言你不应该为此使用实体。你为什么要更改数据以及用户将如何处理它,因为它不再代表数据库中的内容。将进行哪些其他更改或哪些其他假设(这是一个数据库对象)将无效?
如果您使用数据库对象派生不同的对象,您应该为此目的使用不同的 class。这很常见,称为数据传输对象 (DTO),它们可以直接使用投影从 spring-data-jpa 创建。您的 Dto 对象会将一个实体作为构造函数,并从该实体中填写它想要的任何属性。 Dto 不是持久对象,因此保存它没有问题。
更清晰易懂的设计,与 SOLID Principles and code structure 一致。
我有一种情况,我想检索数据,但在 returned 之前,我想在没有 saving/persisting 的情况下更改它。
这是我的休息控制器:
@RestController
@RequestMapping("api/drawing-releases")
@CrossOrigin("*")
public class DrawingReleaseRestController {
@Autowired
private DrawingReleaseService service;
@RequestMapping(method = RequestMethod.GET, value = "/{id}")
@JsonView(View.DrawingReleaseView.class)
public ResponseEntity<DrawingRelease> getWithId(@PathVariable int id) throws EntityNotFoundException {
return new ResponseEntity<>(service.getByID(id),HttpStatus.OK);
}
}
这是服务实现:
@Service
public class DrawingReleaseServiceImpl extends DrawingFunctions implements DrawingReleaseService {
/**
* Logging Manager
*/
private static final Logger LOGGER=LogManager.getLogger();
@Autowired
private DrawingReleaseRepository repository;
@Override
public DrawingRelease getByID(int id) throws EntityNotFoundException {
Optional<DrawingRelease> opt = repository.findById(id);
...
// manipulate the data here
...
return opt.get();
}
}
最初我在服务上有 @Transactional
注释。通过删除它而不是在 getByID
方法上使用它,我首先认为会话将按照答案 here.
那没有用,我在评论中看到 "the session lasts for the entire duration of HTTP request processing." 所以,在我添加的服务中
@Autowired
private EntityManager em;
然后在 getByID
方法中我添加了
em.close();
在我进行任何更改之前。但是,我所做的任何更改仍会保留。
有什么方法可以在我的服务层中进行未保存的更改?我想我可以创建一些 POJO 来镜像实体(但不是实体),然后复制数据和 return 这些对象,但我似乎不必做那样的事情。
是的,您可以 detach
来自持久性上下文的实体:https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#detach-java.lang.Object-
你说你想获得一个实体然后更改数据然后 return 它没有实体被持久化但是恕我直言你不应该为此使用实体。你为什么要更改数据以及用户将如何处理它,因为它不再代表数据库中的内容。将进行哪些其他更改或哪些其他假设(这是一个数据库对象)将无效?
如果您使用数据库对象派生不同的对象,您应该为此目的使用不同的 class。这很常见,称为数据传输对象 (DTO),它们可以直接使用投影从 spring-data-jpa 创建。您的 Dto 对象会将一个实体作为构造函数,并从该实体中填写它想要的任何属性。 Dto 不是持久对象,因此保存它没有问题。
更清晰易懂的设计,与 SOLID Principles and code structure 一致。