最近用 Next.js 和 typeorm 完成了前端小白的第一个全栈项目,本文会记录我在做项目的过程中学习到的一些知识点,和遇到的那些奇奇怪怪的 Bug
Github - 献上源码地址
博客系统 - 献上预览地址,喜欢的话就留下一篇博客吧
上篇文章 - 记录了初始化项目的过程,这么文章初始化数据库
初始化数据库
什么是 ORM
ORM 是 Object–relational mapping 的简称,这个技术的作用是通过实例对象的语法,完成关系型数据库的操作的技术 从这个例子可以看出,ORM 的写法,明显更方便简洁
SELECT id, first_name, last_name, phone, birth_date, sex FROM persons WHERE id = 10------ 改成 ORM 的写法 p = Person.get(10); name = p.first_name;复制代码
TypeORM
Typeorm 是一个可以使用 JavaScript 和 Typescript 来操作数据库的库,目前是 0.2.30 版本,还没发布 v1.0.0 我本打算用 Sequelize.js,但是发现它对 TS 支持不好,于是选用了这个库,它有以下特点
- 默认支持 TypeSciprt
- 支持关联 Associations
- 支持事物 Transactions
- 支持数据库迁移 Migration
简单的介绍旧就说到着,开始敲代码吧
创建数据库
创建数据库目录
- 在项目目录里创建 blog-data 目录
- .gitignore 里添加 /blog-data/
启动 PostgreSQL
一句命令启动 pg
docker run -v "$PWD/blog-data":/var/lib/postgresql/data -p 5432:5432 -e POSTGRES_USER=blog -e POSTGRES_HOST_AUTH_METHOD=trust -d postgres:12.2复制代码
如果报错,可以看这篇教程,或者直接google 搜索吧
如果下载速度慢 先搜阿里云 Docker 镜像 (要登录阿里云),再搜 Docker 加速
启动完成后
docker ps -a // 这句话查看容器状态 docker logs 容器id 这句话查看启动日志复制代码
SQL 创建
一个成熟的 orm 框架一般会提供创建数据的 API,但是 Typeorm 并没有,那就只能手动了 ????
进入 docker 容器
docker exec -it 容器id bash // 容器id 可以通过 docker ps -a 查询复制代码
进入 pg
psql -U blog -W复制代码
由于启动 pg 的时候,设置成无需密码了,所以直接回车就能进入 如果需要加密码,可在 docker run 选项里面的 -e POSTGRES_HOST_AUTH_METHOD=trust 替换成 -e POSTGRES_PASSWORD=123456
创建数据库
按照正式的开发流程,我们需要创建三个数据库: 开发、测试、生产
分别是 blog_development、blog_test、 blog_production
CREATE DATABASE blog_development ENCODING 'UTF8' LC_COLLATE 'en_US.utf8' LC_CTYPE 'en_US.utf8';复制代码
一些常用的 pg 命令
\l 用于 list databases,展示数据库 \c 用于连接数据库 \dt 用于展示数据库中的table复制代码
此时使用 \l 命令,看到这样就是成功啦~
安装 TypeORM
安装依赖
yarn add typeorm reflect-metadata @types/node pg复制代码
修改 tsconfig
"compilerOptions": {"emitDecoratorMetadata": true,"experimentalDecorators": true, }复制代码
运行 npx typeorm init --database postgres 初始化 Typeorm
这个命令会帮我们创建一些文件包括:
src │ ├── entity // 实体 │ │ └── User.ts │ ├── index.ts │ └── migration // 迁移复制代码
其中 index.ts 和 User.ts 都是官方的例子,我们可以先删掉,后面根据自己需求再创建
最后在 ormconfig.json 中配置我们的数据库信息:
"username": "blog","password": "","database": "blog_development"复制代码
禁用 sync -- 重要配置
在 ormconfig.json 文件中将 "synchronize": "ture" 改为 "false"
如果是 true,那么在连接数据库时,typeorm 会自动根据 entity 目录来修改数据表
假设 entity 里面有 User,就会自动创建 User 表
看起来很方便呀,为什么要禁用呢
因为 sync 功能可能会在我们修改 User 时直接删数据
这种行为绝对不能发生在生产环境,所以我们要一开始就杜绝 sync 功能
如何运行 TypeScript
矛盾
Next.js 默认使用 babel 来将 TS 编译为 JS (内置功能)
TypeORM 推荐使用 ts-node 来编译 (没有内置)
babel 和 ts-node 对 TS 的支持并非完全一致
所以我们统一使用 babel 来编译 TS
安装 babel
先将 Node.js 升级到 v14,然后安装 @babel/cli yarn @babel/cli
然后使用 babel 将 src 中的 TS 文件编译为 JS
npx babel ./src --out-dir dist --extensions ".ts,.tsx"复制代码
敲击回车,啪,很快哟
但是没成功,还报了一堆错
经验告诉我,遇到错误不要慌
抓住错误使劲搜
Support for the experimental syntax 'decorators-legacy' isn't currently enabled
经过几个小时的搜索终于有结果了 ????
I had the same problem
那就跟着操作做吧
安装插件
yarn add --dev @babel/plugin-proposal-decorators复制代码
接着是修改 .babelrc 文件,我们没有,那就创建一个
现在在 next.js 的官网中,查到默认配置,然后加上答案的配置
{ "presets": ["next/babel"], "plugins": [ ["@babel/plugin-proposal-decorators", { "legacy": true }] ] }复制代码
重新运行刚刚失败的命令
成功啦~
那么问题来了,编译后的 JS 代码在哪里呢?
--out-dir dist --extensions ".ts,.tsx" 看看运行的命令 --out-dir dist 那当然是 dist 文件了
此时直接运行 node dist/index.js 还是出现报错了
修改 ormconfig.json
因为ormconfig.json 还是默认配置,我们运行 node dist/index.js 还是会运行 src 下的 entity、migrations、subscribers 文件
修改 ormconfig
"entities": [ "dist/entity/**/*.js"],"migrations": [ "dist/migration/**/*.js"],"subscribers": [ "dist/subscriber/**/*.js"]复制代码
再次运行 node dist/index.js 成功啦!
工作流总结
步骤
- 统一让 Next.js 和 TypeORM 使用 babel 翻译 TS
- 每次修改 src 的 TS 代码后,翻译为 dist 里面的 JS
- 使用 node 运行 dist 里面的 JS,执行 TypeORM 任务
这篇文章记录了数据库的初始化过程,那么下篇文章一起来使用 TypoORM 操作数据库吧