java - 对实体对象 spring/JPA/Java 进行验证的缺点
问题描述
据我所知,有一个原则是不要创建具有不适当字段值的类实例。为了处理这个问题,我使用具有所有必要字段的类构造函数。然后我检查参数并在参数错误时抛出异常。
在 JPA 实体类中使用此解决方案是否合适,或者我应该在服务层中检查它?
参数在控制器层上验证,然后使用 Hibernate 注释进行保存。
@Entity
public class Person {
@Id
@GeneratedValue
private Long id;
@Column(name = ColumnNames.NAME, nullable = true)
@Size(min = 2, max = 50, message = "{person.name.size}")
String name;
@Column(name = ColumnNames.DATE_OF_BIRTH, nullable = true)
private LocalDate dateOfBirth;
protected Person(){}
public Person(String name, LocalDate dateOfBirth)
throws IllegalArgumentException, NullPointerException {
Objects.requireNonNull(name);
Objects.requireNonNull(dateOfBirth);
Preconditions.checkArgument(name.length() > 1,
"Name should have length more than 1 character");
this.name = name;
this.dateOfBirth = dateOfBirth;
}
//getters
}
解决方案
首先让我们弄清楚典型MVC
架构中的三个主要组件。
控制器:控制器组件充当您的输入和业务逻辑之间的网关。您可以在此处指定要开发的 API 类型,是GET
请求还是POST
请求?它应该接受什么样的数据?您的 API 应该返回什么作为响应。该层还用于验证来自用户的数据,这样我们就不会在服务层中完成所有繁重的工作,然后得出结论,我们没有合适的数据开始。在我们总结出数据的完整性之后,我们将继续进行实际的逻辑实现区域Service。
服务:服务应该为 API 提供业务逻辑,因此作为存储库的抽象,服务应该是唯一可以访问存储库的服务。这是完成所有繁重工作的地方,如果认为有必要,我们然后解析到存储库层以访问数据库。
存储库:这是最接近数据库的层,它只是用来处理应用程序和数据库之间的所有通信。
谈到你的情况,你想对实体本身进行验证,它有一些缺点。
- 安全性:如果您对实体本身进行验证,您通常会将其暴露在控制器级别,这被认为是一个很大的安全问题,因为您通常会暴露您的表结构,从而使应用程序易受攻击。
- 重量级:本应处理此问题的所有其他层将仅充当通道,这会增加执行所有工作的实体的负载。
- 维护:您可能会遇到不同的规范,具体取决于 API 本身。然后你别无选择,只能用更新的验证重写一个全新的实体,这会降低你的可重用性。
如果我不清楚,请随时联系
.
推荐阅读
- linux - 如果不退出,如何将文本行添加到文件中
- ibm-rational - 在录制 http 代理期间 rpt 打开它时 IE lan 设置恢复
- python - 如何在函数名之外捕获带有类名的函数名?
- amazon-mws - MWS API 报告时间限制是否适用于正在添加的数据或报告中的数据?
- ibm-cloud - API Connect >在此服务器上未找到请求的 URL
- javascript - 如何在 lit-element 中聚焦纸张输入
- extjs - 如何在 ExtJS6 中使用本地(内存)存储将过滤器功能应用于分页网格?
- vb.net - COM+ 组件调用其他 COM+ 组件 - “无法加载类型”
- javascript - 调用对象时使用对象的成员而不是对象本身
- angular - 使用角度动态添加具有唯一 ID 的 div 元素