我正在用Spring Boot从头开始开发我的第一个RESTful API。
我已经为“独立”实体创建了endpoint、模型和JPA存储库。但现在我开始将它们联系在一起,在做了一些研究之后,我得出结论,我可能必须创建DTO。我不认为每次我通过POST请求创建新的订单
,我都应该让客户将整个客户
和员工
对象作为订单
的嵌套对象发送到请求中(如果我在这方面也有错误,请告诉我)。我正在考虑创建一个DTO,只需将类关系替换为ID即可。
这是我的实体当前的定义方式:
@Data
@Entity
@Table(name = "Orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@NotBlank
@NotNull
private String description;
@NotBlank
@NotNull
private Status status;
@NotNull
@ManyToOne
@JoinColumn(foreignKey = @ForeignKey(name = "employee_id_fk"))
private Employee employee;
@NotNull
@ManyToOne
@JoinColumn(foreignKey = @ForeignKey(name = "customer_id_fk"))
private Customer customer;
protected Order() {}
public Order(String description) {
this.description = description;
this.status = Status.IN_PROGRESS;
}
}
以及我的endpoint(这是我必须更改的):
@PostMapping("/orders")
ResponseEntity<EntityModel<Order>> createOrder(@Valid @RequestBody Order order) {
order.setStatus(Status.IN_PROGRESS);
Order newOrder = repository.save(order);
return ResponseEntity
.created(linkTo(methodOn(OrderController.class).getOrder(newOrder.getId())).toUri())
.body(assembler.toModel(newOrder));
}
现在,我应该如何用这种格式验证请求?如您所见,在前面,我只会使用@Valid
,当针对订单
模型调用endpoint时,它会自动得到验证。但是,如果我创建DTO,我必须使用相同的方法验证DTO,并从其模型复制所有注释(@NotNull
,@NotBlank
,等等)。也许我应该在从DTO映射实体模型之后对其进行验证,但我不知道这有多简单,也不知道这是否是验证请求的良好实践。我也无法从实体模型中删除验证,因为我正在使用Hibernate将它们映射到表。
伟大的问题!
我不认为每次我用POST请求创建新订单时,我都应该让客户机将请求中的所有Customer和Employee对象作为嵌套的订单对象发送(如果我在这方面也有错误,请让我知道)。
你说得对。这并不是因为我们可以节省位和字节(看起来可能是这样),而是因为您可以向客户询问的信息越少,他/她获得的体验就越好(无论是外部集成器还是同一公司内的前端/后端应用程序)。包含的数据量越少=越容易理解,出错的空间越小。从设计的角度来看,它还使API更干净。是否可以在没有字段的情况下处理您的请求?那么它不应该出现在API中。
现在,我应该如何用这种格式验证请求?如您所见,在前面,我只使用@Valid,当针对订单模型调用endpoint时,它将自动得到验证。但是,如果我创建DTO,我必须使用相同的方法验证DTO,并从其模型复制所有注释(@NotNull、@NotBlank等)。
您还可以使用@Valid
在映射到endpoint的方法中,在控制器内启动DTO验证。但正如您正确提到的,DTO中所有已验证的字段都应该用@NotNull、@NotBlank等注释。作为“复制”问题的解决方案,您可以创建一个基类,在其中定义所有验证,并从中继承DTO和实体。但是请不要这样做!
在DTO和Enity中具有相同的字段和验证规则不被认为是重复的,因为它们是独立的概念,并且每个概念都在其层(DTO-顶层,实体-通常是最低层,数据层)中服务于其特定的目的。有很多例子可以证明这一点(例如这里和这里)
也许我应该在从DTO映射实体模型之后对其进行验证,但我不知道这有多简单,也不知道这是否是验证请求的良好实践。
验证请求是一种最佳实践,许多项目都在遵循它。在您的示例中,这非常简单(从DTO直接映射到实体),但通常您会有一个服务层,在将其交给数据层之前执行一些业务逻辑(即使在您的示例中,我建议将代码从控制器移到服务层)。您不希望将格式错误的请求传递到控制器之外,以便在以后使用过多的if语句和空检查(这会导致难以遵循的防御代码,而且很容易出错)来处理它。
另一个注意事项:您不应该牺牲客户机经验并告诉他们,也不应该强迫自己再添加两个字段,因为它允许一个对象充当DTO和实体,并简化了开发。
最后一点注意:要将字段从DTO映射到实体,可以使用一个对象映射器库。
我发布了简单的数据,比如 到(让它成为)/帖子乌里,例如smth喜欢 我可以验证,该正文不是空的 或者检查,响应的字段具有我们正在设置的值,例如 但我不确定,它的最佳/正确的方式。那么,问题:如何验证,该实体是在发布后创建的,并保证?
我想知道在静态编程语言中创建全局常量的最佳方法是什么。Java,我们将使用一个包含常量的类,我们只需要导入这个类就可以访问所有常量。但是在静态编程语言中,有两种主要的方法: > 您可以创建一个包含所有常量的对象: 对象常量{const valCONST_1="foo"const valCONST_2="bar"const valCONST_3="toto"} 但这不是推荐的方式,正如一位语言开发者
我是一个项目的一部分,我正在尝试添加TypeScript Web Server,这将与Swagger兼容。 什么是最基本的策略来实现它,考虑到容易的可运维性。 > 对于TypeScript,我注意到存在用于从TypeScript接口生成JSON模型的Tyson库。 对于Swagger,我尝试使用“Swagger node restify”库,因为它支持向Swagger添加JSON模型。 然而,我遇
问题内容: 我有一个简单的班级角色: 现在,我想重写其方法equals和hashCode。我的第一个建议是: 但是,当我创建新的Role对象时,其id为null。这就是为什么我对hashCode方法实现有一些问题。现在,我可以简单地返回,但是如果没有RoleName字段,该怎么办?我几乎可以肯定,组成更复杂的示例并不难,而通过返回其字段之一的hashCode不能解决该示例。 因此,我想查看一些指向
我正在使用Swing和Java。我刚刚开始学习MVC。 我对验证表单(视图)所需的方式有点困惑。 我的想法是在我的视图类中创建方法并逐个验证表单组件,但我担心这会违反MVC原则。
如果我有实体类 和一个DTO > 我的问题是我应该在客户端中使用(赢形)吗?或创建另一个类 如果我想要一个方法 我应该把它放在哪里(作为静态的辅助方法,还是放在里面)?我以前认为应该是里面的方法,但是贫血模型不允许有任何方法。