Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果我的验证器需要在验证之前调用数据库,我应该让数据库来处理这个验证吗?_Java_Database_Spring Boot_Validation_Database Design - Fatal编程技术网

Java 如果我的验证器需要在验证之前调用数据库,我应该让数据库来处理这个验证吗?

Java 如果我的验证器需要在验证之前调用数据库,我应该让数据库来处理这个验证吗?,java,database,spring-boot,validation,database-design,Java,Database,Spring Boot,Validation,Database Design,考虑到以下精心设计的琐碎数据库模式: Owner |id|name|age| Car |id|owner_id|model|color| owner_id references Owner(id) 在我的SpringBoot应用程序中,如果我想插入一条新的汽车记录,有两种方法可以防止通过一个不存在的车主id 将insert语句包装在try/catch块中,以捕获SpringsDataIntegrityViolationException 在服务/控制器层中使用验证器。无论如何,这个验证器都

考虑到以下精心设计的琐碎数据库模式:

Owner
|id|name|age|

Car
|id|owner_id|model|color|

owner_id references Owner(id)
在我的SpringBoot应用程序中,如果我想插入一条新的
汽车
记录,有两种方法可以防止通过一个不存在的
车主id

  • 将insert语句包装在try/catch块中,以捕获Springs
    DataIntegrityViolationException
  • 在服务/控制器层中使用验证器。无论如何,这个验证器都需要查询数据库
  • 类验证程序{
    所有者住所所有者住所;
    公共布尔所有者索引(UUID所有者ID){
    Set ownerIds=ownerRepository.fetchAllOwnerIds();
    返回ownerId.contains(ownerId);
    }
    } 
    
    我更喜欢后者(2),但有时我觉得它是多余的,因为你无论如何都需要去数据库。前者让人感觉到几乎所有insert语句都被try/catch块阻塞了

    给出这两个例子,哪一个更好,为什么? 如果你认为有更好的方法来处理这个问题,请在你的答案中加上它。
    如果这个问题在什么地方得到了回答,请告诉我。

    我会选择方法1。这将为我节省额外的应用服务器到db往返的时间

    我假设您将JPA/Hibernate与JDBC连接池一起使用。在方法2中,您将有一个连接,因为两个db查询都是同一会话的一部分。但在同一个连接上,您将执行两个往返,一个用于选择,一个用于插入。我假设从上面的场景来看,用户不在场的可能性是一个失败场景,这种情况很少发生。因此,从本质上讲,您在所有情况下都节省了时间


    关于所有插入的try/catch,我认为您有一个或最多两个(理想情况下只有一个,因为我看不出您需要更多)插入语句到car&可以封装在一个方法中。您可以在这个DAO方法中处理所有数据库约束错误,并从那里抛出javax.validation.ValidationException异常。您的服务类方法可以处理javax.validation.ValidationException异常&您不需要在服务层处理任何JDBC/特定于数据库的错误。

    第二个方法存在TOCTOU问题。猜猜如果在两次检查之间插入具有相同ID的记录会发生什么:您的检查不会检测到它,并且您最终还是使用了第一个选项。更不用说,随着数据库的增长,检索所有ID的速度会越来越慢,内存也会越来越密集。
    try {
      jooq.insertInto(CAR)
      ....
    } catch (DataIntegrityViolationException ex) {
      ....
    }
    
    class CarValidator {
      OwnerRepository ownerRepository;
      
      public boolean ownerIdExists(UUID ownerId) {
        Set<UUID> ownerIds = ownerRepository.fetchAllOwnerIds();
        return ownerIds.contains(ownerId);
      }
    }