通过 ChatGPT,和 DALL·E 3 生成的
在这篇文章中,我们将使用一个简单的 Node.Js API 示例来比较直接执行原始 SQL 与使用对象关系映射器来与 PostgreSQL 数据库进行交互的方法。
具体地讲,比如对于 Raw SQL,我们用node-postgres,比如对于 ORM,我们用[Prisma]。
你可以在这里获取演示代码:这里!
咱们开始吧,行!
开始设置:在我们开始比较这两种方法之前,先设置好数据库和Node.js相关的项目。
在数据库中建表postgres
数据库中 public
模式里一个简单的 users
表。
CREATE TABLE postgres.public."users" (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
name VARCHAR(80) NOT NULL
)
/ 此 SQL 代码片段直接使用,无需翻译,因为它是一种不需要翻译的技术语法。/
搭建 Node.js 项目用yarn
启动我们的项目,再装上express
用来做路由
创建一个名为 `javascript+sql` 的文件夹 `mkdir javascript+sql`
切换到 `javascript+sql` 目录下 `cd javascript+sql`
使用 Yarn 初始化一个新的 Node.js 项目 `yarn init`
安装 Express 框架到项目中 `yarn add express`
创建一个名为 `index.js` 的新文件 `touch index.js`
index.js
这将是我们的项目起点,以下代码将被使用。
import express from 'express';
var server = express();
server.listen(80);
server.get('/', async function (request, response) {
return response.json({
"message": "来自Itsuki的问候,你好!"
});
});
你可以运行 node index.js
(或者如果你想在更改时自动重新编译,可以运行 nodemon index.js
),然后在浏览器中访问 http://localhost:80
来进行快速测试。
我们接下来要开始使用纯SQL了。
我将使用Node-postgres来进行演示用。这是我最喜欢的一个库,文档非常详尽,有很多示例。
安装在命令行中输入以下命令来安装pg包:
使用npm安装 pg
连接到数据库:
我们将通过创建一个新的 [pg.Pool](https://node-postgres.com/apis/pool)
实例来连接数据库,如下所示。
// 从'pg'模块导入数据库操作库
import pg from 'pg';
// 解构赋值获取Pool对象
const { Pool } = pg;
// 创建一个新的数据库连接池
const pool = new Pool({
// 数据库主机地址从环境变量获取
host: process.env.HOST,
// 数据库用户名从环境变量获取
user: process.env.USER,
// 数据库密码从环境变量获取
password: process.env.PASSWORD,
// 数据库名从环境变量获取
database: process.env.DATABASE,
// 数据库端口号从环境变量获取
port: process.env.PORT,
// 设置空闲超时时间为30000毫秒
idleTimeoutMillis: 30000,
});
池最初为空,并在需要时按需创建新客户端。
我在这里列出了 config
对象的所有字段,但这些字段都是可选的。当池创建客户端实例时,该配置也会传递给池中每个客户端实例。
我将用插入和查询为例。
不管我们在做什么操作,要运行直接的 SQL 查询,我们将会调用 [pool.query](https://node-postgres.com/features/queries)
,比如。client.query
支持同样的 API。实际上,pool.query
实际上是在内部直接调用 client.query
。
export class PgManager {
// 插入用户信息
async 插入用户(username) {
const insertUser = `
插入到 public.users
(name)
值为($1)
返回所有列
`;
const result = await pool.query(insertUser, [username]);
// 输出结果到控制台
console.log(result)
const userCreated = result.rows[0];
return userCreated
}
// 查询所有用户信息
async 查询用户() {
const result = await pool.query("SELECT * FROM postgres.public.users");
// 输出结果到控制台
console.log(result)
const users = result.rows;
return users
}
}
要将参数传递给查询,我们可以通过拼接字符串,或者像上面那样使用带参数的查询。
我们只需要用几个端点来测试一下上面提到的它们。
const pgManager = new PgManager();
server.post('/pg/users', async function (request, response) {
try {
if ("username" in request.query) {
const username = request.query.username;
const createdUser = await pgManager.insertUser(username);
return response.json({
"user": createdUser
});
} else {
throw new Error('用户名未提供');
}
} catch (error) {
return response.json({
"error": `${error}`
});
}
});
server.get('/pg/users', async function (request, response) {
try {
const users = await pgManager.queryUsers();
return response.json({
"users": users
});
} catch (error) {
return response.json({
"error": `${error}`
});
}
});
这里以 GET localhost:80/pg/users
为例。
对我来说,这种方法最大的好处是不需要任何构建过程,也不需要抽象的概念。
当你在编写自动化测试时看到一个可以访问数据库的选项,这非常棒,因为你只需要写你的正常 SQL 并运行它!不需要设置!
我上面使用了 JavaScript,但你也可以使用 TypeScript 以获得一些类型安全性。例如,我们可以这样定义一个 interface
User
:
用户接口 {
id: 用户ID;
name: 名称;
} // 用户接口,定义用户ID和名称
并且用它来限制我们的回应
const users: User[] = await pgManager.queryUsers(); // 从pgManager查询用户列表并赋值给users
不足之处
接下来,让我们来看看这种方法存在的问题。
- 没有单源实况(Single Source of Truth,SSOT)
- 没有内置的迁移处理方式
- 没有验证SQL查询的正确性
- 没有确保类型的准确性的手段
Prisma(https://www.prisma.io/docs)是一个用于 Node.js 和 TypeScript 的 ORM,它具有直观的数据模型、自动化迁移和类型安全性。
是的,上面说的所有问题都已经考虑到了。
还有一些其他的知名 ORM,比如 TypeORM 和 Sequelize。你可以自己试试这些 ORM,找到你最喜欢的。在这里我们会用 Prisma。
安装命令行界面 (CLI)你需要安装 Prisma CLI。
在命令行中输入以下命令来安装 prisma
:
npm install prisma --save-dev
开始设置(开始吧)接下来,我们得运行一下来设置我们的项目
运行以下命令来初始化 Prisma:
npx prisma init
此命令将会如下
- 创建一个名为
prisma
的新文件夹,其中包含一个名为schema.prisma
的文件,该文件包含了您的数据库连接变量和 Prisma 模型定义。 - 在项目根目录中创建
[.env](https://www.prisma.io/docs/orm/more/development-environment/environment-variables/env-files)
文件,用于定义数据库连接所需的环境变量。
记得去编辑 .env
文件里的 DATABASE_URL
,改成你自己的数据库地址。它应该采用以下格式。
例如: postgresql://USER:PASSWORD@HOST:PORT/数据库?schema=模式
也确认你的prisma/schema.prisma
包含如下内容。如果你在使用typescript,你的provider可能会有一些不同之处。
生成器 client {
提供器 = "prisma-client-js"
}
数据源 db {
提供器 = "postgresql"
url = env("DATABASE_URL")
}
模型数据信息
为了能够与我们的users
表互动,我们首先需要为users
表创建一个模型。
用户模型 users {
id String @db.Uuid @id @default(dbgenerated("gen_random_uuid()")) // 默认生成随机UUID
name String
}
如果你还没有设置好数据库表,你可以在这里运行命令 npx prisma migrate
来将数据模型映射到数据库模式中。具体来说,这个命令会执行以下操作:
- 在
prisma/migrations
目录下为这次迁移创建一个新的 SQL 迁移文件。 - 将 SQL 迁移文件执行到数据库上。
- 后台运行了
prisma generate
命令(自动安装了@prisma/client
包,并根据你的模型生成了定制的 Prisma 客户端 API)。
但我们已经有了数据库和表的搭建,我们就可以直接运行 npx prisma generate
。
为了在项目中开始使用 Prisma 客户,我们需要安装 @prisma/client
包。
npm install @prisma/client
在这里,我们使用npm安装@prisma/client包。
数据操作我知道,配置真的超级多,但这样做有好处!
这里告诉你怎么插入和查询的操作。
import { PrismaClient } from '@prisma/client' // 引入PrismaClient模块
const prisma = new PrismaClient() // 创建PrismaClient实例
// PrismaManager类用于管理和操作用户数据
export class PrismaManager {
/**
* 插入用户方法,接受一个username参数,并创建一个新用户
* @param username 用户名
* @returns 返回创建的用户对象
*/
async insertUser(username) {
const userCreated = await prisma.users.create({
data: {
name: username // 设置用户名
},
})
console.log(userCreated) // 输出创建的用户信息
return userCreated // 返回创建的用户对象
}
/**
* 查询用户方法,返回所有用户列表
* @returns 返回一个包含所有用户对象的数组
*/
async queryUsers() {
const users = await prisma.users.findMany() // 查询所有用户
return users // 返回用户列表
}
}
执行任何操作的基本格式是 {客户端}.{表名}.{操作}
。
简洁的代码逻辑,不含硬编码的SQL语句。
好处:这个项目是你最准确的信息来源。
你有内建的方法来处理迁移问题。
类型和数据库模式保持一致。
我真的想说“简单的数据操作”已经不再足够了,如果你想进行更多的个性化查询,比如添加WHICH
、WHERE
等这样的关键词就变得很重要。
当然,你也可以直接在 Prisma 中执行原始 SQL,那么为什么不用 pg
直接操作呢?
太多了!
太多的设置显然会让大型或复杂数据库难以承受。
行了!
我不真的喜欢!
感谢阅读!希望这篇文章能帮助您在做决定时选择哪个更好!
我很想知道您对此的看法或您更喜欢的迁移工具使用Raw SQL库时!留下您的评论哦!
开心连上啦!
栈学 🎓感谢你一直读到最后。在你离开之前,还有几句话要说:
- 请考虑点赞并关注作者!👏
- 关注我们 X | LinkedIn | YouTube | Discord
- 您可以访问我们其他的平台:In Plain English | CoFeed | Differ
- 更多内容请访问我们的网站 Stackademic.com