首页 > 解决方案 > 对实体对象 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
}

标签: javajpaormentity

解决方案


首先让我们弄清楚典型MVC架构中的三个主要组件。

控制器:控制器组件充当您的输入和业务逻辑之间的网关。您可以在此处指定要开发的 API 类型,是GET请求还是POST请求?它应该接受什么样的数据?您的 API 应该返回什么作为响应。该层还用于验证来自用户的数据,这样我们就不会在服务层中完成所有繁重的工作,然后得出结论,我们没有合适的数据开始。在我们总结出数据的完整性之后,我们将继续进行实际的逻辑实现区域Service

服务:服务应该为 API 提供业务逻辑,因此作为存储库的抽象,服务应该是唯一可以访问存储库的服务。这是完成所有繁重工作的地方,如果认为有必要,我们然后解析到存储库层以访问数据库。

存储库:这是最接近数据库的层,它只是用来处理应用程序和数据库之间的所有通信。

谈到你的情况,你想对实体本身进行验证,它有一些缺点。

  • 安全性:如果您对实体本身进行验证,您通常会将其暴露在控制器级别,这被认为是一个很大的安全问题,因为您通常会暴露您的表结构,从而使应用程序易受攻击。
  • 重量级:本应处理此问题的所有其他层将仅充当通道,这会增加执行所有工作的实体的负载。
  • 维护:您可能会遇到不同的规范,具体取决于 API 本身。然后你别无选择,只能用更新的验证重写一个全新的实体,这会降低你的可重用性。

如果我不清楚,请随时联系

.


推荐阅读