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
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);
}
}