简体   繁体   English

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

[英]should i use jpa entity in rest request and/or response

I have a situation in which i can send JPA entity as rest request and/or get JPA entity as rest response我有一种情况,我可以发送 JPA 实体作为休息请求和/或获取 JPA 实体作为休息响应

@RequestMapping(value = "/products", method = RequestMethod.POST)
public @ResponseBody ProductDetailsResponse createNewProduct(@RequestBody ProductDetails newProduct)
        throws Exception {

ProductDetails is an entity ProductDetails是一个实体

@Entity
@Table(name = "product")
public class ProductDetails {

Should I use this, or have some kind of transformation from entities to another kind of objects我应该使用它,还是从实体到另一种对象进行某种转换

There is no hard and fast rule but its not considered a good practice ( for very good reasons & Its very opinionated view ) to use JPA entities as DTOs ( Data Transfer Objects ).没有硬性规定,但将 JPA 实体用作 DTO(数据传输对象)并不被认为是一种好的做法(出于非常好的理由和非常固执的观点)。

Other than DTOs being lightweight versions of entities in terms of size, there are other advantages too.除了 DTO 在大小方面是实体的轻量级版本之外,还有其他优势。

One such advantage that I realized is lighter versions of relationships too eg for a One - To - Many unidirectional relationship , your child entity will reference back your parent entity too but you can break that chain in DTOs so avoid lots of JSON conversion and infinite looping related issues.我意识到的一个优点是关系的更轻版本,例如对于一对多的单向关系,您的子实体也将引用您的父实体,但您可以在 DTO 中打破该链,从而避免大量 JSON 转换和无限循环相关问题。

I find doing JSON to Object conversions ( and vice versa ) at DTO level a bit easier than at entity level because entities represent DB diagram not client business diagram.我发现在 DTO 级别进行 JSON 到对象转换(反之亦然)比在实体级别更容易一些,因为实体代表数据库图而不是客户端业务图。

One simple generic utility class to do conversions ( from DTO to Entity and vice - versa ) will be enough.一个简单的通用实用程序类来进行转换(从 DTO 到实体,反之亦然)就足够了。 You can use model mapper API as described here .您可以使用此处所述的模型映射器 API。

I don't let entities cross service layer boundary, its all DTOs at controller and I do conversions at controller.我不让实体跨越服务层边界,它在控制器上的所有 DTO,我在控制器上进行转换。

There are very interesting questions on SO on this topic that you can browse ,您可以浏览有关此主题的 SO 上的非常有趣的问题,

Should I convert an entity to a DTO inside a Repository object and return it to the service layer? 我应该将实体转换为 Repository 对象内的 DTO 并将其返回到服务层吗?

Conversion of DTO to entity and vice-versa DTO 与实体的转换,反之亦然

REST API - DTOs or not? REST API - DTO 与否?

Additional boiler plate code is one disadvantage of DTO approach.额外的样板代码是 DTO 方法的一个缺点。

From technical point of view, it is fine to use entity in response.从技术角度来看,使用实体作为响应是可以的。 Entity must just be serializable to response output format (JSON or XML).实体必须可序列化为响应输出格式(JSON 或 XML)。

It is good idea to write test that will create complete entity object (all fields set to non null) and try to serialize it.编写测试以创建完整的实体对象(所有字段设置为非空)并尝试序列化它是个好主意。 Even single non-serializable field will cause exception.即使是单个不可序列化的字段也会导致异常。 You rather want to discover that during testing than after release.您更愿意在测试期间而不是在发布之后发现这一点。

In simple cases (CRUD applications), where every field of entity is needed in response this is fine option.在简单的情况下(CRUD 应用程序),需要实体的每个字段作为响应,这是一个不错的选择。

If you do not need every field of entity in response, you may use @JsonView.如果您不需要实体的每个字段作为响应,您可以使用@JsonView。

If your response is significantly diffrent than entity (new fields, transformations) it is better idea to create separate DTO object for response.如果您的响应与实体(新字段、转换)明显不同,最好为响应创建单独的 DTO 对象。 That way, you will be able to evolve web API (DTO) and datatabase schema (entity) separately.这样,您将能够分别发展 Web API (DTO) 和数据库架构(实体)。

No don't do it.不,不要这样做。 It has nothing to do with Good practice or some fancy pattern or anything.它与良好实践或一些花哨的模式或任何东西无关。

Here are the reasons:原因如下:

A JPA Entity, if we are talking Hibernate is associated with a Hibernate Session. JPA 实体,如果我们说的是 Hibernate,则与 Hibernate Session 相关联。 As such Hibernate can do somethings with unintended consequences.因此,Hibernate 可以做一些意想不到的事情。 Lets take a look:让我们来看看:

1) Flush Mode - Flush is equivalent to a SQL update, hibernate will check for "dirty state" of an Object based on certain rules then do: 1) Flush Mode - Flush 相当于 SQL 更新,hibernate 将根据某些规则检查对象的“脏状态”,然后执行:

       entityManager.flush();

You may not have intended to be calling "sqlStatement.update" but lo and behold here we go您可能不打算调用“sqlStatement.update”,但是瞧,我们走了

2) 2)

`class EntityA{
     //  Defaults to Lazy Fetch
     @OneToMany
     private Set<EntityB> entityBees
 }

If we do the following from your controller and the Hibernate Session is closed you get Exceptions such as Detached entity, etc:如果我们从您的控制器执行以下操作并且休眠会话已关闭,您将收到异常,例如分离的实体等:

for (EntityB b : entityA.getEntityBees) {
    //  This is a problem
    process(b);
}

To reiterate, its not coz of some fancy GoF pattern, its coz it is dangerous.重申一下,这不是因为某些花哨的 GoF 模式,而是因为它很危险。 Particularly if you do not know what you are doing.特别是如果您不知道自己在做什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM