Sequelize-Automate: 自动生成 Sequelize Models
小伙伴们对数据库编程感兴趣吗?是否正在学习相关知识点?如果是,那么本文《Sequelize-Automate: 自动生成 Sequelize Models》,就很适合你,本篇文章讲解的知识点主要包括MySQL、前端、Node.js、javascript、sequelize。在之后的文章中也会多多分享相关知识点,希望对大家的知识积累有所帮助!
本文的主角是 sequelize-automate
背景
Sequelize 是 Node.js 中常用的 ORM 库,其作用就是对数据库表和代码中的对象做一个映射,让我们能够通过面向对象的方式去查询和操作数据库。
举个例子,数据库可能有一张
class UserModel extends Model {} User.init({ id: DataTypes.INTEGER, name: DataTypes.STRING, birthday: DataTypes.DATE }, { sequelize, modelName: 'userModel' });
然后可以通过
CREATE TABLE `user` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'primary ket', `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'user name', `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'user email', `created_at` datetime NOT NULL COMMENT 'created datetime', `updated_at` datetime NOT NULL COMMENT 'updated datetime', PRIMARY KEY (`id`), UNIQUE KEY `uk_name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='User table'
则使用 sequelize-automate 可以自动生成的 Model 文件为
const { DataTypes } = require('sequelize'); module.exports = sequelize => { const attributes = { id: { type: DataTypes.INTEGER(11).UNSIGNED, allowNull: false, defaultValue: null, primaryKey: true, autoIncrement: true, comment: "primary key", field: "id" }, name: { type: DataTypes.STRING(100), allowNull: false, defaultValue: null, primaryKey: false, autoIncrement: false, comment: "user name", field: "name", unique: "uk_name" }, email: { type: DataTypes.STRING(255), allowNull: false, defaultValue: null, primaryKey: false, autoIncrement: false, comment: "user email", field: "email" }, created_at: { type: DataTypes.DATE, allowNull: false, defaultValue: null, primaryKey: false, autoIncrement: false, comment: "created datetime", field: "created_at" }, updated_at: { type: DataTypes.DATE, allowNull: false, defaultValue: null, primaryKey: false, autoIncrement: false, comment: "updated datetime", field: "updated_at" } }; const options = { tableName: "user", comment: "", indexes: [] }; const UserModel = sequelize.define("user_model", attributes, options); return UserModel; };
这样我们就可以在项目中直接使用了:
const Sequelize = require('sequelize'); const UserModel = require('./models/user'); // Option 1: Passing parameters separately const sequelize = new Sequelize('database', 'username', 'password', { host: 'localhost', dialect: /* one of 'mysql' | 'mariadb' | 'postgres' | 'mssql' | 'sqlite' */ }); const userModel = UserModel(sequelize); const users = await userModel.findAll();
Sequelize-Automate 使用
$ npm install -g sequelize-automate
然后还需要安装使用的数据库对应的依赖包,这点与 sequelize 一致:
# 根据你使用的数据库,从下面的命令中选一个安装即可 $ npm install --save pg pg-hstore # Postgres $ npm install --save mysql2 $ npm install --save mariadb $ npm install --save sqlite3 $ npm install --save tedious # Microsoft SQL Server
当然,如果你已经在项目中使用了 sequelize,则一定会安装一个对应的数据库依赖包。
安装成功后,你就可以在项目目录中通过
"scripts": { "sequelize-automate": "sequelize-automate" },
这样就可以通过
sequelize-automate -t js -h localhost -d test -u root -p root -P 3306 -e mysql -o models
如果在项目中使用的话,则可以将改命令添加到 package.json 中:
"scripts": { "sequelize-automate": "sequelize-automate -t js -h localhost -d test -u root -p root -P 3306 -e mysql -o models" },
然后通过
{ "dbOptions": { "database": "test", "username": "root", "password": "root", "dialect": "mysql", "host": "localhost", "port": 3306, "logging": false }, "options": { "type": "js", "dir": "models" } }
当然也可以使用 JS 文件:
module.exports = { dbOptions: { database: "test", username: "root", password: "root", dialect: "mysql", host: "localhost", port: 3306, logging: false }, options: { type: "js", dir: "models" } }
然后就可以通过
dbOptions: { database: 'test', username: 'root', password: 'root', dialect: 'mysql', host: '127.0.0.1', port: 3306, define: { underscored: false, freezeTableName: false, charset: 'utf8mb4', timezone: '+00:00', dialectOptions: { collate: 'utf8_general_ci', }, timestamps: false, }, };
通常我们会用到的就是
options: { type: 'js', // 指定 models 代码风格 camelCase: false, // Models 文件中代码是否使用驼峰发命名 fileNameCamelCase: true, // Model 文件名是否使用驼峰法命名,默认文件名会使用表名,如 `user_post.js`;如果为 true,则文件名为 `userPost.js` dir: 'models', // 指定输出 models 文件的目录 typesDir: 'models', // 指定输出 TypeScript 类型定义的文件目录,只有 TypeScript / Midway 等会有类型定义 emptyDir: false, // 生成 models 之前是否清空 `dir` 以及 `typesDir` tables: null, // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性 skipTables: null, // 指定跳过哪些表的 models,如 ['user'];如果为 null,则忽略改属性 tsNoCheck: false, // 是否添加 `@ts-nocheck` 注释到 models 文件中 }
所有参数可以参考源码:src/index.js#L13。
这里补充一点,之所以有
// @ts-nocheck import { IApplicationContext, providerWrapper } from 'midway'; import { DataTypes } from 'sequelize'; import { IDB } from './db'; export default async function setupModel(context: IApplicationContext) { const db: IDB = await context.getAsync('DB'); const attributes = { id: { type: DataTypes.BIGINT.UNSIGNED, allowNull: false, defaultValue: null, primaryKey: true, autoIncrement: true, comment: '主键', field: 'id', }, name: { type: DataTypes.STRING(100), allowNull: false, defaultValue: null, primaryKey: false, autoIncrement: false, comment: null, field: 'name', }, }; const options = { tableName: 'flow', comment: '', indexs: [], }; return db.sequelize.define('userModel', attributes, options); } providerWrapper([{ id: 'UserModel', provider: setupModel, }]);
API
上面主要讲了 sequelize-automate 的命令行使用方式,sequelize-automate 本身也提供了接口,让使用者自定义开发。主要有两个:
-
const Automate = require('sequelize-automate'); // dbOptions 和 options 前面已经提到,这里不再赘述 const dbOptions = { // ... }; const options = {} // ... } // 创建一个 automate 实例 const automate = new Automate(dbOptions, options); (async function main() { // // 获取 Models JSON 定义 // const definitions = await automate.getDefinitions(); // console.log(definitions); // 或生成代码 const code = await automate.run(); console.log(code); })()
Sequelize-Automate 的实现
sequelize-automate 的实现思路很简单,就是首先从数据库中查询到所有表信息,包括表结构、索引、外键等,然后将表信息转换为一个 JSON 定义,最后使用 AST 根据 JSON 定义去生成代码。
获取表信息
查询表信息依赖了 sequelize 的一些方法,这也是为什么 sequelize-automate 依赖了 sequelize,并且有个参数是
{ "user":{ "structures":{ "id":{ "type":"INT(11) UNSIGNED", "allowNull":false, "defaultValue":null, "primaryKey":true, "autoIncrement":true, "comment":"primary ket" }, "name":{ "type":"VARCHAR(100)", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"user name" }, "email":{ "type":"VARCHAR(255)", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"user email" }, "created_at":{ "type":"DATETIME", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"created datetime" }, "updated_at":{ "type":"DATETIME", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"updated datetime" } }, "indexes":[ { "primary":true, "fields":[ { "attribute":"id", "order":"ASC" } ], "name":"PRIMARY", "tableName":"user", "unique":true, "type":"BTREE" }, { "primary":false, "fields":[ { "attribute":"name", "order":"ASC" } ], "name":"uk_name", "tableName":"user", "unique":true, "type":"BTREE" } ], "foreignKeys":[ ] }, "user_post":{ "structures":{ "id":{ "type":"INT(11) UNSIGNED", "allowNull":false, "defaultValue":null, "primaryKey":true, "autoIncrement":true, "comment":"primary key" }, "user_id":{ "type":"INT(11) UNSIGNED", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"user id" }, "title":{ "type":"VARCHAR(255)", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"post title" }, "content":{ "type":"TEXT", "allowNull":true, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"post content" }, "created_at":{ "type":"DATETIME", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"created datetime" }, "updated_at":{ "type":"DATETIME", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"updated datetime" } }, "indexes":[ { "primary":true, "fields":[ { "attribute":"id", "order":"ASC" } ], "name":"PRIMARY", "tableName":"user_post", "unique":true, "type":"BTREE" }, { "primary":false, "fields":[ { "attribute":"user_id", "order":"ASC" } ], "name":"fk_user_id", "tableName":"user_post", "unique":false, "type":"BTREE" } ], "foreignKeys":[ { "constraint_name":"fk_user_id", "constraintName":"fk_user_id", "constraintSchema":"test", "constraintCatalog":"test", "tableName":"user_post", "tableSchema":"test", "tableCatalog":"test", "columnName":"user_id", "referencedTableSchema":"test", "referencedTableCatalog":"test", "referencedTableName":"user", "referencedColumnName":"id" } ] } }
处理 Models JSON 定义
得到表信息后,就需要将表信息转换为 sequelize models 的定义。比如:将
[ { "modelName":"user_model", "modelFileName":"user", "tableName":"user", "attributes":{ "id":{ "type":"DataTypes.INTEGER(11).UNSIGNED", "allowNull":false, "defaultValue":null, "primaryKey":true, "autoIncrement":true, "comment":"primary ket", "field":"id" }, "name":{ "type":"DataTypes.STRING(100)", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"user name", "field":"name", "unique":"uk_name" }, "email":{ "type":"DataTypes.STRING(255)", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"user email", "field":"email" }, "created_at":{ "type":"DataTypes.DATE", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"created datetime", "field":"created_at" }, "updated_at":{ "type":"DataTypes.DATE", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"updated datetime", "field":"updated_at" } }, "indexes":[ ] }, { "modelName":"user_post_model", "modelFileName":"user_post", "tableName":"user_post", "attributes":{ "id":{ "type":"DataTypes.INTEGER(11).UNSIGNED", "allowNull":false, "defaultValue":null, "primaryKey":true, "autoIncrement":true, "comment":"primary key", "field":"id" }, "user_id":{ "type":"DataTypes.INTEGER(11).UNSIGNED", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"user id", "field":"user_id", "references":{ "key":"id", "model":"user_model" } }, "title":{ "type":"DataTypes.STRING(255)", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"post title", "field":"title" }, "content":{ "type":"DataTypes.TEXT", "allowNull":true, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"post content", "field":"content" }, "created_at":{ "type":"DataTypes.DATE", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"created datetime", "field":"created_at" }, "updated_at":{ "type":"DataTypes.DATE", "allowNull":false, "defaultValue":null, "primaryKey":false, "autoIncrement":false, "comment":"updated datetime", "field":"updated_at" } }, "indexes":[ { "name":"fk_user_id", "unique":false, "type":"BTREE", "fields":[ "user_id" ] } ] } ]
而后续的
const t = require('@babel/types'); const str = t.stringLiteral('Primary key'); // { type: 'StringLiteral', value: 'Primary key' }
生成对象
const obj = t.objectProperty(t.identifier('comment'), t.stringLiteral("Primary key")); /** { type: 'ObjectProperty', key: { type: 'Identifier', name: 'comment' }, value: { type: 'StringLiteral', value: 'Primary' }, computed: false, shorthand: false, decorators: null } */
然后就可以根据 AST 生成代码:
const generator = require('@babel/generator').default; const code = generate(obj); // { code: 'comment: "Primary"', map: null, rawMappings: null }
需要注意的是,如果要支持中文,则需要设置
const obj = t.objectProperty(t.identifier('comment'), t.stringLiteral("主键")); const code1 = generate(obj); { code: 'comment: "\\u4E3B\\u952E"', map: null, rawMappings: null } const code2 = generate(obj, { jsescOption: { minimal: true, }, }); // { code: 'comment: "主键"', map: null, rawMappings: null }
总结
最开始写 sequelize-automate 是因为每次表结构修改了,都需要手动在代码里面修改 models ,修改起来非常繁琐而且容易写错,当表非常多的时候,写起来就更麻烦了。所以开发了这个小工具,能够让工具做的事情,就尽量让工具去做。
在写 sequelize-automate 之前,其实我也发现了
sequelize/sequelize-auto
也可以用来自动生成 models,但这个包已经几年没有更新了,使用的 sequelize 还是 3.30 版本,现在 sequelize 已经更新到 6.0 了;并且它还有很多 BUG 没有修复,很难使用起来。我也去看了它的代码,感觉很混乱,全是回调嵌套,难以维护。其生成代码也是用的字符串拼接的方式,没有 AST 先进、高端、准确且可预测。所以,毫不犹豫的选择并使用 sequelize-automate 吧!今天关于《Sequelize-Automate: 自动生成 Sequelize Models》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于mysql的内容请关注golang学习网公众号!

- 上一篇
- 阿里云RDS vs 自建MySQL,选择困难?这篇评测为你讲的明明白白!

- 下一篇
- 技术分享 | MySQL 在 NoSQL 领域冲锋陷阵
-
- 聪明的眼睛
- 这篇技术文章真及时,太全面了,真优秀,mark,关注老哥了!希望老哥能多写数据库相关的文章。
- 2023-03-09 12:03:46
-
- 数据库 · MySQL | 1天前 |
- MySQL设置中文界面,超简单教程来了!
- 332浏览 收藏
-
- 数据库 · MySQL | 1天前 | mysql 索引提示
- MySQL进阶必看!FORCE/USE/IGNOREINDEX用法大揭秘
- 182浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- 手把手教你写MySQL存储过程,小白也能轻松上手
- 163浏览 收藏
-
- 数据库 · MySQL | 1天前 | mysql group by
- MySQL分组查询优化:GROUPBY原理+索引优化超全解析
- 324浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL设置中文语言,轻松拥有中文界面
- 211浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL建库语句从入门到精通:创建数据库+设置字符集&排序规则(附实例)
- 176浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- 从零开始学MySQL数据库操作,小白轻松变大神!
- 496浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL插入日期到时间字段,轻松搞定日期格式
- 484浏览 收藏
-
- 数据库 · MySQL | 1天前 | mysql 数据压缩
- MySQL怎么实现高效压缩存储?表压缩+列式存储详细解读
- 272浏览 收藏
-
- 数据库 · MySQL | 1天前 | mysql JOIN优化
- MySQL优化JOIN操作:七大技巧教你提升关联查询速度
- 106浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL出现中文乱码?超详细解决方案一次性搞定
- 211浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL主从复制这样配!搞懂这些参数,replication稳了~
- 131浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 茅茅虫AIGC检测
- 茅茅虫AIGC检测,湖南茅茅虫科技有限公司倾力打造,运用NLP技术精准识别AI生成文本,提供论文、专著等学术文本的AIGC检测服务。支持多种格式,生成可视化报告,保障您的学术诚信和内容质量。
- 14次使用
-
- 赛林匹克平台(Challympics)
- 探索赛林匹克平台Challympics,一个聚焦人工智能、算力算法、量子计算等前沿技术的赛事聚合平台。连接产学研用,助力科技创新与产业升级。
- 48次使用
-
- 笔格AIPPT
- SEO 笔格AIPPT是135编辑器推出的AI智能PPT制作平台,依托DeepSeek大模型,实现智能大纲生成、一键PPT生成、AI文字优化、图像生成等功能。免费试用,提升PPT制作效率,适用于商务演示、教育培训等多种场景。
- 56次使用
-
- 稿定PPT
- 告别PPT制作难题!稿定PPT提供海量模板、AI智能生成、在线协作,助您轻松制作专业演示文稿。职场办公、教育学习、企业服务全覆盖,降本增效,释放创意!
- 51次使用
-
- Suno苏诺中文版
- 探索Suno苏诺中文版,一款颠覆传统音乐创作的AI平台。无需专业技能,轻松创作个性化音乐。智能词曲生成、风格迁移、海量音效,释放您的音乐灵感!
- 56次使用
-
- golang MySQL实现对数据库表存储获取操作示例
- 2022-12-22 499浏览
-
- 搞一个自娱自乐的博客(二) 架构搭建
- 2023-02-16 244浏览
-
- B-Tree、B+Tree以及B-link Tree
- 2023-01-19 235浏览
-
- mysql面试题
- 2023-01-17 157浏览
-
- MySQL数据表简单查询
- 2023-01-10 101浏览