在 Egg.js 中使用 Modelar ORM
发布于 7 年前 作者 Hyurl 6270 次浏览 来自 分享

Egg.js 并不自带 ORM,这篇文章将向你介绍如何在 Egg 中使用 Modelar ORM。

Modelar 非常容易使用,因此你不需要向 sequelize 那样要封装一个 egg-sequelize 模块 才能使用,直接使用就好。

首先,你需要创建一个项目,名称例如 egg-modelar

mkdir egg-modelar
cd egg-modelar
npm init
npm install egg
npm install egg-bin
npm install modelar

然后按照 Eggjs 官网所介绍的,在生成的 package.json 中添加下面的 script 命令

// package.json
{
    "name": "egg-modelar",
    "scripts": {
        "dev": "egg-bin dev"
    }
}

然后,先创建一个默认配置文件,来设置 cookie 密钥并关闭 csrf 检测(测试需要)。文件名为 config/config.default.js,内容为:

// config/config.default.js
exports.keys = "my-cookie";

exports.security = {
    csrf: {
        enable: false,
    },
};

接下来,我们需要扩展一下 context 对象,将一个在数据库对象绑定在整个请求过程中。

// extend/context.js
const { DB } = require("modelar"); // npm install modelar

module.exports = {
    get db(){
        if (!this.db) {
            this.db = new DB({
                type: "mysql",
                database: "modelar",
                host: "127.0.0.1",
                port: 3306,
                user: "root",
                password: "161301"
            });
        }
        return this.db;
    }
};

另外,还需要在响应发送给客户端之后,自动回收数据库连接。创建一个名为 middleware/releasedb.js 的文件,内容如下:

// middleware/releasedb.js
module.exports = options => {
    return async (ctx, next) => {
        // 添加一个事件处理器,当响应被发送回客户端后,回收数据库连接并等待下一个请求
        // 取回它。
        ctx.res.on("finish", () => {
            ctx.db.release();
        });
        await next();
    }
};

并在 config.default.js 中加入下面这一行内容

exports.middleware = ["releasedb"];

接下来,我们创建一个 Article 模型,用来管理文章。文件名为 model/article.js, 内容为:

// model/article.js
const { Model } = require("modelar");

module.exports = class Article extends Model{
    constructor(data = {}) {
        super(data, {
            table: "articles",
            primary: "id",
            fields: ["id", "title", "content"],
            searchable: ["title", "content"]
        });
    }
};

然后,在控制器中使用它。创建一个新的控制器 app/controller/article.js,内容如下:

// app/controller/article.js
const { Controller } = require('egg');
const { Table } = require("modelar");
const Article = require("../model/article");

module.exports = class extends Controller {
    /** 创建一个名称为 articles 的表 */
    async createTable() {
        const { ctx } = this;
        ctx.status = 200;
        try {
            var table = new Table("articles");
            table.addColumn("id").primary().autoIncrement();
            table.addColumn("title", "varchar", 255).notNull();
            table.addColumn("content", "varchar", 1024).notNull();

            // 保存表并向客户端返回消息
            table = await table.use(ctx.db).save();
            ctx.body = {
                success: true,
                data: "数据表创建成功!",
            };
        } catch (e) {
            ctx.body = {
                success: false,
                msg: e.message,
            };
        }
    }

    /** 创建一个篇新文章 */
    async create() {
        const { ctx } = this;
        ctx.status = 200;
        try {
            var article = new Article;
            article.title = "A new article in Modelar circumstance.";
            article.content = "This is the content of the article.";

            // 保存用户并向客户端返回消息
            article = await article.use(ctx.db).save();
            ctx.body = {
                success: true,
                data: article,
            };
        } catch (e) {
            ctx.body = {
                success: false,
                msg: e.message,
            };
        }
    }

    /** 获取用户 */
    async get() {
        const { ctx } = this;
        ctx.status = 200;
        try {
            var article = await Article.use(ctx.db).get(ctx.params.id);
            ctx.body = {
                success: true,
                data: article,
            };
        } catch (e) {
            ctx.body = {
                success: false,
                msg: e.message,
            };
        }
    }
}

并在 app/router.js 文件中为控制器分配路由地址:

// app/router.js
module.exports = app => {
    const { router, controller } = app;

    router.post('/article/create-table', controller.article.createTable);
    router.post("/article/create", controller.article.create);
    router.get("/article/:id", controller.article.get);
};

最后启动服务器来进行测试:

npm run dev

推荐使用可视化的工具,如 Chrome 的 RESTED 插件来模拟请求。

项目地址:https://github.com/hyurl/modelar

文档地址:http://modelar.hyurl.com

3 回复

赞一个,不过看了下,还是要封装个插件才更友好,如 releasedb 这个如果是必备的,就应该在插件里面自动挂载,不应该给到应用开发者去搞

@atian25 你去封装吧,我不是很了解 eggjs 的插件机制,我不是用 eggjs 的

我这边没使用场景,留给有需要的社区开发者吧

回到顶部