java - 如果我的验证器需要在验证之前调用数据库,我应该让数据库处理这个验证吗?
问题描述
给定以下人为的和琐碎的数据库模式:
Owner
|id|name|age|
Car
|id|owner_id|model|color|
owner_id references Owner(id)
在我的 SpringBoot 应用程序中,如果我想插入一条新Car
记录,有两种方法可以防止传递一个不存在的owner_id
.
- 将插入语句包装在 try/catch 块中以捕获 Springs
DataIntegrityViolationException
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);
}
}
我更喜欢后者(2),但有时我觉得它是多余的,因为无论如何您都需要访问数据库。前者感觉就像你最终用 try/catch 块阻塞了几乎所有的插入语句。
鉴于这两个例子哪个更好,为什么?如果您认为有更好的方法来处理此问题,请将其添加到您的答案中。如果这已在某处得到回答,请指出我。
解决方案
我会采用方法 1。它将为我节省额外的应用程序服务器到 db 往返的时间。
我假设您正在使用 JPA/Hibernate 和 JDBC 连接池。在方法二中,您将拥有一个连接,因为两个数据库查询都将属于同一会话。但是在同一个连接上,您将进行两次往返,一次用于选择,一次用于插入。而且我从上述场景中假设,用户不存在的机会是一种失败场景,这种情况会发生很少。因此,基本上,在所有情况下,您都在节省时间。
关于所有插入的 try/catch,我认为您有一个或最多两个(理想情况下只有一个,因为我看不出为什么需要更多)插入语句到 car & 可以封装在一个方法中。您可以在这个单一的 DAO 方法中处理所有数据库约束错误,并从那里抛出 javax.validation.ValidationException 异常。您的服务类方法可以处理 javax.validation.ValidationException 异常,并且您不需要处理服务层中的任何 JDBC/数据库特定错误。
推荐阅读
- c# - 如何以角度(打字稿)将图像存储为字节数组
- javascript - Html Transistion 仅在重新加载后第一次滞后
- oracle - 管理包中异常的最佳方法
- reactjs - 如何使用本地存储访问组合的 reducer 值 React-Redux
- spring-boot - Spring Boot如何在运行时重用现有连接更改数据库?
- python - 替换默认管理站点时模块未定义类错误
- css - Flex wrap 仅在我取消选中并签入检查元素时才起作用
- c++ - 多个返回语句
- javascript - discord.js 停止机器人在错误后关闭
- graphql - 类型 graphql - 无视多态类型