我应该在休息请求和/或响应中使用jpa实体

时间:2017-07-02 15:30:01

标签: java hibernate rest jpa

我有一种情况,我可以发送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 {

我应该使用它,还是从实体到另一种对象进行某种转换

3 个答案:

答案 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

REST API - DTOs or not?

额外的锅炉板代码是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模式,因为它是危险的。特别是如果您不知道自己在做什么。