我正在使用 路由器 -> 控制器 -> 服务 -> 数据访问 架构构建 REST API。
大多数教程/示例项目都会像这样进行创建和更新(在 DAO 中):
例如 freecodecamp.com Node.js REST API 教程中的代码:
const createNewWorkout = (newWorkout) => {
try {
const isAlreadyAdded =
DB.workouts.findIndex((workout) => workout.name === newWorkout.name) > -1;
if (isAlreadyAdded) {
throw {
status: 400,
message: `Workout with the name '${newWorkout.name}' already exists`,
};
}
DB.workouts.push(newWorkout);
saveToDatabase(DB);
return newWorkout;
} catch (error) {
throw { status: error?.status || 500, message: error?.message || error };
}
};
const updateOneWorkout = (workoutId, changes) => {
try {
const isAlreadyAdded =
DB.workouts.findIndex((workout) => workout.name === changes.name) > -1;
if (isAlreadyAdded) {
throw {
status: 400,
message: `Workout with the name '${changes.name}' already exists`,
};
}
const indexForUpdate = DB.workouts.findIndex(
(workout) => workout.id === workoutId
);
if (indexForUpdate === -1) {
throw {
status: 400,
message: `Can't find workout with the id '${workoutId}'`,
};
}
const updatedWorkout = {
...DB.workouts[indexForUpdate],
...changes,
updatedAt: new Date().toLocaleString("en-US", { timeZone: "UTC" }),
};
DB.workouts[indexForUpdate] = updatedWorkout;
saveToDatabase(DB);
return updatedWorkout;
} catch (error) {
throw { status: error?.status || 500, message: error?.message || error };
}
};
然而,数据库操作在服务器资源方面是昂贵的。尝试创建/更新,如果需要的话让操作失败(主键已存在的记录,更新缺少必填字段等),然后捕获错误不是更好吗?也许将所有内容封装在存储过程中,这确实可能仍然首先检索数据以进行一些检查,但可以由数据库进行优化?
您可以使用外键将您想要执行的所有验证移至数据库中,检查约束和触发器,如果验证失败,则会引发异常,然后在应用程序代码中处理失败/成功。
如果 INSERT/UPDATE 的验证依赖于大量数据,特别是如果您使用多个查询来获取该数据,那么效率可能会更高。将验证移至数据库中将为您节省网络往返次数。数据库可能会优化查询验证所需的数据和验证操作本身,但最有可能节省网络往返将是最大的时间节省。