我有一种情况,我可以发送JPA实体作为休息请求和/或获取JPA实体作为休息响应
@RequestMapping(value = "/products", method = RequestMethod.POST)
public @ResponseBody ProductDetailsResponse createNewProduct(@RequestBody ProductDetails newProduct)
throws Exception {
ProductDetails
是一个实体
@Entity
@Table(name = "product")
public class ProductDetails {
我应该使用它,还是从实体到另一种对象进行某种转换
答案 0 :(得分:10)
没有严格的规则,但是将JPA实体用作DTO(数据传输对象)并不是一个好的做法(非常好的理由和非常自以为是的观点)。
除了DTO在尺寸方面是轻量级实体之外,还有其他优点。
我意识到的一个这样的优势就是更轻松的关系版本,例如对于一对多单向关系,您的子实体也将引用您的父实体,但您可以在DTO中打破该链,以避免大量JSON转换和无限循环相关问题。
我发现在DTO级别进行JSON到Object转换(反之亦然)比在实体级别更容易,因为实体代表DB图而不是客户业务图。
进行转换的一个简单的通用实用程序类(从DTO到实体,反之亦然)就足够了。您可以使用模型映射器API,如here所述。
我不允许实体跨服务层边界,它的所有DTO都在控制器上,我在控制器上进行转换。
关于此主题的SO有一些非常有趣的问题,您可以浏览,
Should I convert an entity to a DTO inside a Repository object and return it to the service layer?
Conversion of DTO to entity and vice-versa
额外的锅炉板代码是DTO方法的一个缺点。
答案 1 :(得分:4)
从技术角度来看,在实际应用中使用实体是可以的。实体必须只能序列化为响应输出格式(JSON或XML)。
最好编写将创建完整实体对象的测试(所有字段设置为非null)并尝试序列化它。即使单个非可序列化字段也会导致异常。您更愿意在测试期间发现它而不是在发布之后。
在简单的情况下(CRUD应用程序),响应中需要每个实体字段,这是一个很好的选择。
如果您不需要响应中的每个实体字段,则可以使用@JsonView。
如果您的响应与实体(新字段,转换)明显不同,则最好为响应创建单独的DTO对象。这样,您将能够单独发展Web API(DTO)和数据库架构(实体)。
答案 2 :(得分:0)
不,不要这样做。它与良好实践或某些幻想模式无关。
原因如下:
如果我们正在谈论Hibernate,则JPA实体与Hibernate会话相关联。这样,Hibernate会做一些意想不到的后果。让我们看看:
1)刷新模式-刷新等效于SQL更新,休眠将基于某些规则检查对象的“脏状态”,然后执行以下操作:
entityManager.flush();
您可能不打算调用“ sqlStatement.update”,但请看这里
2)
`class EntityA{
// Defaults to Lazy Fetch
@OneToMany
private Set<EntityB> entityBees
}
如果我们从您的控制器执行以下操作,并且Hibernate会话已关闭,您将获得异常,例如分离的实体等:
for (EntityB b : entityA.getEntityBees) {
// This is a problem
process(b);
}
重申一下,它不是某种花哨的GoF模式,因为它是危险的。特别是如果您不知道自己在做什么。