sequelize
在Egg项目中安装和使用sequelize步骤:
1.下载egg-sequelize:
npm install --save egg-sequelize mysql2
-
在plugin.js 文件中引入插件
module.exports = { sequelize: { enable: true, package: 'egg-sequelize' } } -
在config.default.js文件中配置数据库连接
config.sequelize = { dialect: 'mysql', database: 'mysqlname', host: 'localhost', port: 3306, username: 'root', password: '123456', timezone: "+08:00", //时区转换 // 时间自动转字符串格式化 dialectOptions: { dateStrings: true, typeCast: true, }, define: { timestamps: true, } };MySQL数据库与sequelize数据类型对应如下
1. STRING => varchar(255) 2. INTEGER => int 3. DOUBLE => double 4. DATE => datetime 5. TEXT => text 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 Sequelize.DATE(6) // DATETIME(6) 小数秒支持6位精度 Sequelize.DATEONLY // DATE 不带时间 Sequelize.BOOLEAN // TINYINT(1) -
在app/model文件中创建数据库模型
在app/model目录中创建clazz.js文件,对应数据库中的clazz表
module.exports = app => { const { STRING } = app.Sequelize; // 默认情况下,sequelize将自动将所有传递的模型名称(define的第一个参数)转换为复数 const Clazz = app.model.define('clazz', { name: STRING, }) return Clazz; } -
添加app.js文件,初始化数据库
在项目根目录中创建app.js文件,初始化数据库
module.exports = app => { app.beforeStart(async function() { // 开发环境使用,会删除数据表 // await app.model.sync({ force: true }); await app.model.sync({}); }); };在controller中实现数据的增删改查
说明: 在真实的项目中,controller和操作数据的逻辑要分离,以便项目的扩展与维护。
// 查询数据 this.app.model.Clazz.findAll(); // 通过id查询 this.app.model.Clazz.findByPk(1); // 通过wherre设置查询条件 this.app.model.Clazz.findOne({ where: { id: 1 } }); // 添加数据 this.app.model.Clazz.create({ name: "xx" }); // 通过条件修改数据 this.app.model.Clazz.update({ name: "xx" }, { where: { id: 1} }); // 通过条件删除数据 this.app.model.Clazz.destroy({ where: { id: 1 } });在Student与clazz之间一对多和多对一的表关联
- 创建一个名为clazz的班级表,包含id和name两个字段
module.exports = (app) => { const { STRING, INTEGER, BOOLEAN } = app.Sequelize; const Clazz = app.model.define("clazz", { id: { type: INTEGER, autoIncrement: true, primaryKey: true, }, name: { type: STRING, allowNull: false, }, }); // 建立联系 Clazz.associate = function () { // 课程和学生一对多,用hasmany,用学生的clazz_id作为外键参考,和自己的id字段匹配 // clazz 有很多 Student, clazz当作是集合(主),student当作是元素(次) // 知道主次就能较好的记忆了 // targetKey当作是班级牌号,foreignKey当作是学生找班牌号的参考 // 理解成把学生按照什么分类到班级里去,就稍微好记一点 app.model.Clazz.hasMany(app.model.Student, { foreignKey: "clazz_id", targetKey: "id", }); }; return Clazz; };- 学生的模型
// 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, }, clazzId: { type: INTEGER, allowNull: false, }, name: { type: STRING(16), allowNull: false, }, }); Student.associate = function () { // 学生与班级是多对一, belongsTo属于谁 // 学生属于班级,学生是次,班级是主,foreignKey在学生里面找,targetKey在班级找 app.model.Student.belongsTo(app.model.Clazz, { foreignKey: "clazzId", targetKey: "id", }); }; return Student; };总结:
-
先确定表之间的关系
-
表一和表二是一对多的话建立联系的时候在模型里面是
表一模型.associate = function(){ 表一模型.hasMany(表二模型,{ foreignKey: 次的字段,targetKey: 主的字段 }) } -
表二和表一建立链接的时候就是belongsTo
表二模型.associate = function(){ 表二模型.belongsTo(表一模型,{ foreignKey: 次的字段,targetKey: 主的字段 }) } -
分清楚主次,上面可以看出表一是主,表二是次
-
通式化:
表一模型.hasMany(表二模型,{ foreignKey: 表二的字段,targetKey: 表一的字段 }) 表二模型.belongsTo(表一模型,{ foreignKey: 表二的字段,targetKey: 表一的字段 }) -
如果是一对一(主次可调换) ,由上可得
表一模型.hasOne(表二模型,{ foreignKey: 表二的字段,targetKey: 表一的字段 }) 表二模型.belongsTo(表一模型,{ foreignKey: 表二的字段,targetKey: 表一的字段 })
多对多
多对多: 学生和老师,一个老师有多个学生,一个学生有多个老师 要确定某条数据需要同时确定学生和老师的关系 一般需要第三张表进行记录,比如把某个学生的id和某个老师的id组合当成一行数据记录,来确定
代码简写如下
student.js
Student.associate = function (){ // 与Teacher存在多对多关系,使用belongsToMany() app.model.Student.belongsToMany(app.model.Teacher, { // 通过TeacherStudent模型对应的表查询 // foreignKey和Student匹配的值,再匹配otherKey的值 // 例如: student表的id和TeacherStudent表的studentId匹配上了 // 然后得到teacherId去和teacher表匹配得到的结果就是这个id的学生的老师 through: app.model.TeacherStudent, // 注意驼峰还是下划线, // 模型配置里面underscored默认为true,把驼峰转换为下划线 foreignKey: 'studentId', //这两个字段是主键或者是外键类型和两张表对应 otherKey: 'teacherId' }); } return Student;teacher.js
Teacher.associate = function(){ app.model.Teacher.belongsToMany(app.model.Student, { through: app.model.TeacherStudent, foreignKey: 'teacherId', otherKey: 'studentId' }); } return Teacher;teacherStudent.js
TeacherStudent.associate = function(){} return TeacherStudent;contro.js
// contro.js async info(){ const { ctx, app } = this; //学生有哪些老师 let result = await app.m.Student.findAll({ include: { model: app.m.Teacher } }); ctx.body = result; // 每个老师有哪些学生 // let result = await app.m.Teacher.findAll({ // include: { // model: app.m.Student // } // }); // ctx.body = result; }总结:
多对多是固定的格式
表一模型.belongsToMany(表二模型, { through: 中间表模型, foreignKey: '在中间表里面和表一匹配的字段', otherKey: '在中间表里面和表二匹配的字段' }); 查询还是 await app.m.Student.findAll({ include: { model: app.m.Teacher } });
定义 service
在app/servicr目录下创建student.js文件
const Service = require('egg').Service;
class StudentService extends Service {
async getStudentList() {
// orm操作
}
}
module.exports = StudentService;