Eggjs筆記:集成sequelize orm

關於Sequelize

在一些較爲複雜的應用中,我們可能會需要一個ORM框架來幫助我們管理數據層的代碼。
而在 Node.js 社區中,sequelize 是一個廣泛使用的 ORM 框架,它支持 MySQL、SQLite 和 MSSQL 、PostgreSQL 等多個數據源。

相關文檔

  • https://eggjs.org/zh-cn/tutorials/sequelize.html
  • https://sequelize.org/

Sequelize 操作 Mysql 數據庫

安裝 egg-sequelize 以及 mysql2

$ npm i --save egg-sequelize mysql2

在 config/plugin.js 中引入 egg-sequelize 插件

exports.sequelize = { 
    enable: true,
    package: 'egg-sequelize',
};

在 config/config.default.js 中編寫 sequelize 配置

config.sequelize = { 
    dialect: 'mysql',
    host: '127.0.0.1', 
    port: 3306, 
    database: 'test', 
    username:"root", 
    password:"123456"
};

Sequelize 操作 Mysql 實現增刪改查

1.在 app/model/ 目錄下編寫數據庫 Model, 以用戶表 user 爲例

'use strict';

module.exports = app => {
    const { STRING, INTEGER, DATE } = app.Sequelize;
    const User = app.model.define('user', {
        id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 
        name: STRING(255),
        age: INTEGER,
        created_at: DATE,
        updated_at: DATE,
    });
    return User; 
};

'use strict';

module.exports = app => {
    const { STRING, INTEGER, DATE } = app.Sequelize;
    const User = app.model.define('user', {
        id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 
        name: STRING(30),
        age: INTEGER,
        created_at: DATE,
        updated_at: DATE,
    },{
        freezeTableName: true,
        tableName: 'user_info', // 指定表名
        timestamps: false, // 表示:不自動增加創建時間
    });
    return User; 
};

注意:這裏定義的model是user,對應數據庫的表名就應該是users 複數的形式,第二種方式是自定義指定表名

2、定義 controller 實現數據庫的增刪改查

async index() {
    const ctx = this.ctx;
    // ctx.body = await ctx.model.User.findAll();
    ctx.body = await ctx.model.User.findAll({limit: 10, offset: 0, order:[["id","desc"]]});
    // 指定返回的字段
    //ctx.body = await ctx.model.User.findAll({attributes: ['id', 'name'], limit: 10, order:[["id","desc"]]});
    // 查詢條件
    //ctx.body = await ctx.model.User.findAll({attributes: ['id', 'name'], order:[["id","desc"]], where:{id:1}});
}

async findOne() {
    const ctx = this.ctx;
    var result = await ctx.model.User.findByPk(1); // 根據主鍵來查找數據
    ctx.body=result || ''; 
}

async create() {
    const ctx = this.ctx;
    const user = await ctx.model.User.create({ name:"張三", age:20 }); 
    ctx.status = 201;
    ctx.body = user;
}

async update() {
    const ctx = this.ctx;
    const id = 1;
    const user = await ctx.model.User.findByPk(id); 
    if (!user) {
        ctx.status = 404;
        return; 
    }
    await user.update({ name:"李四", age:43 });
    ctx.body = user;
}

async destroy() {
    const ctx = this.ctx;
    const id = 3;
    const user = await ctx.model.User.findByPk(id); 
    if (!user) {
        ctx.status = 404;
        return; 
    }
    await user.destroy(); 
    ctx.status = 200; 
    ctx.body="刪除成功";
}

Sequelize 操作多表關聯查詢

注:圖片託管於github,請確保網絡的可訪問性

1 對 1 hasOne 或者 belongsTo

文章和文章分類的關係是:一對一的關係,一篇文章對應一個分類,使用 hasOne , belongsTo

app/model/article.js

'use strict';

module.exports = app => {
  const { STRING, INTEGER, DATE } = app.Sequelize;

  const Article = app.model.define('article', {
    id: { type: INTEGER, primaryKey: true, autoIncrement: true },
    title: STRING(255),
    description: INTEGER,
    cateId:STRING(30),
    state: DATE   
  },{
    timestamps: false,
    tableName: 'article'    
  });
 
  Article.associate = function (){
    // 1對1
    app.model.Article.belongsTo(app.model.ArticleCate, {foreignKey: 'cateId'});  // cateId 是 Article 表的外鍵
  }
 
  return Article;
};

app/controller/article.js

  //查詢數據 1對1
  async index() {
    const { ctx } = this;

    let result = await ctx.model.Article.findAll({
        include: {
          model: ctx.model.ArticleCate
        }
    });

    ctx.body = result;
  }

一對多 hasMany

文章分類和文章的關係是:一對多的關係,一篇文章對應一個分類,使用 hasMany

app/model/article_cate.js

'use strict';

module.exports = app => {
  const { STRING, INTEGER, DATE } = app.Sequelize;

  const ArticleCate = app.model.define('article_cate', {
    id: { type: INTEGER, primaryKey: true, autoIncrement: true },
    title: STRING(255),
    state: INTEGER
  },{
    timestamps: false,  //關閉時間戳
    tableName: 'article_cate'    //配置表名稱 
  });

  ArticleCate.associate = function (){
    // 如果是 1對1 的話就像是下面這樣寫
    // app.model.ArticleCate.hasOne(app.model.Article, {foreignKey: 'cateId'});

    // 文章分類與文章是 1對多,應該這樣
    app.model.ArticleCate.hasMany(app.model.Article, {foreignKey: 'cateId'});
  }
 
  return ArticleCate;
};

app/controller/article.js

  //查詢數據 1對多
  async index() {
    const { ctx } = this;

    let result = await ctx.model.ArticleCate.findAll({
        include: {
          model: ctx.model.Article
        }
    });

    ctx.body = result;
  }

多對多 belongsToMany

有三張表:其中兩張表:課程表和學生表;另外一張關聯表:學生課程的關聯表

app/model/lesson.js

'use strict';

module.exports = app => {
    const { INTEGER, STRING } = app.Sequelize;
 
    const Lesson = app.model.define('lesson', {
        id: {
            type: INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: STRING,
            allowNull: false
        }
    },{
        timestamps: false,
        tableName: 'lesson'    
      });

      Lesson.associate = function () {
        //一個學生可以選修多門課程 
        //一門課程可以被多個學生選修
        app.model.Lesson.belongsToMany(app.model.Student, {
            through: app.model.LessonStudent, 
            foreignKey: 'lessonId',//注意寫法 
            otherKey: 'studentId' 
        });
     }
    return Lesson;
}

app/model/student.js

'use strict';

module.exports = app => {
    const { STRING, INTEGER } = app.Sequelize;

    const Student = app.model.define('student', {
        id: {
            type: INTEGER,
            autoIncrement: true,
            primaryKey: true
        },
        name: {
            type: STRING,
        },
        number: {
            type: STRING,
            allowNull: false,
        },
        password: {
            type: STRING(32),
            allowNull: false
        }
    }, {
        timestamps: false,
        tableName: 'student'
    });

    Student.associate = function () {
        //一個學生可以選修多門課程
        app.model.Student.belongsToMany(app.model.Lesson, {
            through: app.model.LessonStudent, // through 關聯表
            foreignKey: 'studentId',// 注意寫法 駝峯
            otherKey: 'lessonId' 
        });
    }

    return Student;
}

app/model/lesson_student.js

'use strict';

module.exports = app => {
    const { INTEGER } = app.Sequelize;
 
    const LessonStudent = app.model.define('lesson_student', {
        lessonId: {
            type: INTEGER,
            primaryKey: true
        },
        studentId: {
            type: INTEGER,
            primaryKey: true
        }
    },{
        timestamps: false,
        tableName: 'lesson_student'    
      });
 
    //   LessonStudent.associate = function(){
 
    // }
 
    return LessonStudent;
}

控制器 app/controller/test.js 查詢語句:

async index() {
    const { ctx } = this;

    // 查詢課程有哪些學生選修:
    // let result = await ctx.model.Lesson.findAll({
    //   include: {
    //     model:  ctx.model.Student
    //   }
    // });
    

    // 查詢每個學生選修了哪些課程
    let result = await ctx.model.Student.findAll({
      include: {
        model:  ctx.model.Lesson
      }
    });   
    ctx.body = result;
}

Sequelize 常見的數據類型

Sequelize.STRING VARCHAR(255)
Sequelize.STRING(1234) VARCHAR(1234)
Sequelize.STRING.BINARY VARCHAR BINARY
Sequelize.TEXT TEXT
Sequelize.TEXT('tiny') TINYTEXT
Sequelize.INTEGER INTEGER
Sequelize.BIGINT BIGINT
Sequelize.BIGINT(11) BIGINT(11)
Sequelize.FLOAT FLOAT
Sequelize.FLOAT(11) FLOAT(11)
Sequelize.FLOAT(11, 12) FLOAT(11,12)
Sequelize.DOUBLE DOUBLE
Sequelize.DOUBLE(11) DOUBLE(11)
Sequelize.DOUBLE(11, 12) DOUBLE(11,12)
Sequelize.DECIMAL DECIMAL
Sequelize.DECIMAL(10, 2) DECIMAL(10,2)
Sequelize.DATE DATETIME 針對 mysql / sqlite; TIMESTAMP, WITH TIME ZONE 針對 postgres
Sequelize.DATE(6) // DATETIME(6) 針對 mysql 5.6.4+. 小數秒支持多達6位精度
Sequelize.DATEONLY DATE 不帶時間
Sequelize.BOOLEAN TINYINT(1)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章