Node-MySQL_李南江学习笔记

一 node-mysql

/*
1.如何在Node程序中操作MySQL数据库?
我们都知道操作MySQL数据库就是连接MySQL服务器, 给MySQL服务器发送指令
在NodeJS中我们可以借助第三方库来连接MySQL服务器, 给MySQL服务器发送指令
1.1 mysql驱动库
https://www.npmjs.com/package/mysql
npm install mysql
1.2 mysql2驱动库
https://www.npmjs.com/package/mysql2
npm install mysql


2.由于node第三方库还不支持最新的mysql加密, 所以我们需要修改为旧版本加密方式
2.1、更改加密方式:
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER;
2.2、更改密码
mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root';
* */
// 1.导入MySQL第三方驱动库
const mysql      = require('mysql2');
// 2.进行连接配置
var connection = mysql.createConnection({
    host     : '127.0.0.1', // MySQL服务器地址
    port     : 3306,
    user     : 'root',  //  MySQL服务用户名
    password : 'root',  //  MySQL服务密码
    database : 'day17'  // 需要操作的那个数据库的名称

});
// 3.连接MySQL服务器
connection.connect();

// 4.给MySQL服务器发送指令
connection.query('select * from person where id=1', (error, results, fields) => {
    if (error){
        console.log(error);
        return
    }
    console.log(results);
});

// 5.释放连接
connection.end();

二 orm-Sequelize

/*
1.什么是Sequelize?
Sequelize是一个基于Promise的NodeJS ORM模块

2.什么是ORM?
ORM(Object-Relational-Mapping)是对象关系映射
对象关系映射可以把JS中的类和对象, 和数据库中的表和数据进行关系映射
映射之后我们就可以直接通过类和对象来操作数据表和数据了, 就不用编写SQL语句了
ORM有效的解决了直接在NodeJS中编写SQL不够直观, 不够高效, 容易出错等问题

3.如何映射?
在Sequelize中JS中的一个类(一个模型)就对应数据库中的一张表
在Sequelize中JS中的一个对象就对应表中的一条数据(一条记录)
在Sequelize中JS中的一个对象的属性就对应一条数据的一个字段

|---------------------------|
|  id  |   name   |   age   |
|   1  |    zs    |    18   |
|   2  |    ls    |    19   |
|---------------------------|

// 1.创建一张表
cosnt 模型名称 = Sequelize.define('表名', {
    id: int,
    name: varchar(255),
    age: int
})
// 2.创建一条记录
let zs = 模型名称.build({
    id: 1,
    name: zs,
    age: 18
})
zs.id

// 3.操作表和数据
只要是通过Sequelize定义的模型(类), 那么Sequelize就会自动给这个模型添加很多操作表和数据的方法
以后我们就可以直接通过模型操作表, 通过模型创建出来的对象操作数据
* */

三 Sequelize-连接数据库

/*
1.Sequelize基本使用
https://sequelize.org/
*/
/*
2.什么是数据库连接池?
默认情况下有一个人要使用数据库, 那么就必须创建一个连接
默认情况下有一个人不用数据库了, 为了不占用资源, 那么就必须销毁一个连接
但是频繁的创建和销毁连接是非常消耗服务器性能的, 所以为了提升服务器性能就有了连接池

数据库连接池是负责分配、管理和释放数据库连接,
它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
* */

// 1.导入Sequelize
const Sequelize = require('sequelize');
// 2.配置连接信息
/*
第一个参数: 要操作的数据库名称
第二个参数: 数据库用户名
第三个参数: 数据库密码
第四个参数: 其它的配置信息
* */
const sequelize = new Sequelize('demo', 'root', 'root', {
    host: '127.0.0.1', // MySQL服务器地址
    port: 3306, // MySQL服务器端口号
    // 注意点: Sequelize不仅仅能操作MySQL还能够操作其它类型的数据库
    dialect: 'mysql', // 告诉Sequelize当前要操作的数据库类型
    pool: {
        max: 5, // 最多有多少个连接
        min: 0, // 最少有多少个连接
        idle: 10000, // 当前连接多久没有操作就断开
        acquire: 30000, // 多久没有获取到连接就断开
    }
});

// 3.测试配置是否正确
sequelize.authenticate()
.then(()=>{
    console.log('ok');
})
.catch((err)=>{
    console.log(err);
});

四 创建表

// 1.导入Sequelize
const Sequelize = require('sequelize');
// 2.配置连接信息
/*
第一个参数: 要操作的数据库名称
第二个参数: 数据库用户名
第三个参数: 数据库密码
第四个参数: 其它的配置信息
* */
const sequelize = new Sequelize('demo', 'root', 'root', {
    host: '127.0.0.1', // MySQL服务器地址
    port: 3306, // MySQL服务器端口号
    // 注意点: Sequelize不仅仅能操作MySQL还能够操作其它类型的数据库
    dialect: 'mysql', // 告诉Sequelize当前要操作的数据库类型
    pool: {
        max: 5, // 最多有多少个连接
        min: 0, // 最少有多少个连接
        idle: 10000, // 当前连接多久没有操作就断开
        acquire: 30000, // 多久没有获取到连接就断开
    }
});

/*
1.字段说明常用属性
type:  字段类型
primaryKey: 是否是主键
autoIncrement: 是否自动增长
allowNull: 是否允许为空
unique: 是否必须唯一
defaultValue:  默认值
* */
/*
2.额外配置常用属性
timestamps: 是否自动添加createdAt/updateAt字段
freezeTableName: 是否禁止自动将表名修改为复用
tableName:  是否自定义表名
indexes: [ // 指定索引
    {
        name: '', // 索引名称
        fields: [''], // 索引字段名称
    }
]
* */

/*
第一个参数: 用于指定表的名称
第二个参数: 用于指定表中有哪些字段
第三个参数: 用于配置表的一些额外信息
* */
/*
注意点:
1.sequelize在根据模型创建表的时候, 会自动将我们指定的表的名称变成复数
2.sequelize在根据模型创建表的时候, 会自动增加两个字段 createAt/updateAt
* */
let User = sequelize.define('user', {
    id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true
    },
    name: {
        type: Sequelize.STRING, // varchar(255)
        allowNull: false,
        unique: true
    },
    age: {
        type: Sequelize.TINYINT,
        defaultValue: 66
    },
    gender: {
        type: Sequelize.ENUM(['男', '女', '妖']),
        defaultValue: '妖'
    }
}, {
    freezeTableName: true, // 告诉sequelize不需要自动将表名变成复数
    // tableName: 'student', // 自定义表名
    timestamps: false, // 不需要自动创建createAt/updateAt这两个字段
    indexes: [ // 指定索引
        {
            name: 'idx_age', // 索引名称
            fields: ['age'], // 索引字段名称
        }
    ]
});

// 注意点: 默认定义好一个模型之后并不会自动创建对应的表
//         我们需要通过调用连接对象的sync方法来执行同步
//         只有同步之后才会自动根据模型创建对应的表
sequelize.sync();

五 创建数据

// 1.导入Sequelize
const Sequelize = require('sequelize');

(async ()=>{
    // 2.配置连接信息
    /*
    第一个参数: 要操作的数据库名称
    第二个参数: 数据库用户名
    第三个参数: 数据库密码
    第四个参数: 其它的配置信息
    * */
    const sequelize = new Sequelize('day17', 'root', 'root', {
        host: '127.0.0.1', // MySQL服务器地址
        port: 3306, // MySQL服务器端口号
        // 注意点: Sequelize不仅仅能操作MySQL还能够操作其它类型的数据库
        dialect: 'mysql', // 告诉Sequelize当前要操作的数据库类型
        pool: {
            max: 5, // 最多有多少个连接
            min: 0, // 最少有多少个连接
            idle: 10000, // 当前连接多久没有操作就断开
            acquire: 30000, // 多久没有获取到连接就断开
        }
    });

    // 3.创建模型
    let User = sequelize.define('user', {
        id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: Sequelize.STRING, // varchar(255)
            allowNull: false,
            unique: true
        },
        age: {
            type: Sequelize.TINYINT,
            defaultValue: 66
        },
        gender: {
            type: Sequelize.ENUM(['男', '女', '妖']),
            defaultValue: '妖'
        }
    }, {
        freezeTableName: true, // 告诉sequelize不需要自动将表名变成复数
        // tableName: 'student', // 自定义表名
        timestamps: false, // 不需要自动创建createAt/updateAt这两个字段
        indexes: [ // 指定索引
            {
                name: 'idx_age', // 索引名称
                fields: ['age'], // 索引字段名称
            }
        ]
    });
      sequelize.sync();

    // 4.创建一条数据(一条记录)
    // let u = new User();
    // u.name = 'zs';
    // u.age = 33;
    // u.gender = '男';
    /*
    注意点:
    创建好一条数据之后, 默认情况下不会立即同步到表中
    如果想立即同步到表中, 那么必须调用对象的save方法
    注意点:
    本质上让MySQL执行SQL语句是一个异步的操作,
    所以在sequelize中大部分的方法都是异步方法
    注意点:
    通过模型类创建出来的对象中有一个dataValues的属性, 这个属性就保存了一条记录所有的信息
    调用save方法保存完数据之后, sequelize会自动更新对应的对象, 将最新的数据更新进去
    * */
    // console.log('保存之前:', u);
    // await u.save();
    // console.log('保存之后:', u);

    // 下面这段代码 = 创建对象 + save();
    let u = await User.create({
        name: 'ww',
        age: 18,
        gender: '女'
    });
    console.log('保存之后:', u);
    console.log(u.dataValues);
})();

六 操作数据

// 1.导入Sequelize
const Sequelize = require('sequelize');

(async ()=>{
    // 2.配置连接信息
    /*
    第一个参数: 要操作的数据库名称
    第二个参数: 数据库用户名
    第三个参数: 数据库密码
    第四个参数: 其它的配置信息
    * */
    const sequelize = new Sequelize('day17', 'root', 'root', {
        host: '127.0.0.1', // MySQL服务器地址
        port: 3306, // MySQL服务器端口号
        // 注意点: Sequelize不仅仅能操作MySQL还能够操作其它类型的数据库
        dialect: 'mysql', // 告诉Sequelize当前要操作的数据库类型
        pool: {
            max: 5, // 最多有多少个连接
            min: 0, // 最少有多少个连接
            idle: 10000, // 当前连接多久没有操作就断开
            acquire: 30000, // 多久没有获取到连接就断开
        }
    });

    // 3.创建模型
    let User = sequelize.define('user', {
        id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: Sequelize.STRING, // varchar(255)
            allowNull: false,
            unique: true
        },
        age: {
            type: Sequelize.TINYINT,
            defaultValue: 66
        },
        gender: {
            type: Sequelize.ENUM(['男', '女', '妖']),
            defaultValue: '妖'
        }
    }, {
        freezeTableName: true, // 告诉sequelize不需要自动将表名变成复数
        // tableName: 'student', // 自定义表名
        timestamps: false, // 不需要自动创建createAt/updateAt这两个字段
        indexes: [ // 指定索引
            {
                name: 'idx_age', // 索引名称
                fields: ['age'], // 索引字段名称
            }
        ]
    });
    // sequelize.sync();

    // 4.创建一条数据(一条记录)
    
    // let u = new User();
    // u.name = 'zs';
    // u.age = 33;
    // u.gender = '男';
    // await u.save();

    // 下面这段代码 = 创建对象 + save();
    // let u = await User.create({
    //     name: 'ls',
    //     age: 18,
    //     gender: '男'
    // });
    //console.log(u.dataValues);
      

    // 5.查询数据
    // let u = await User.findByPk(2);
    // console.log(u);

    // // 6.修改数据
    // u.name = 'it666';
    // await u.save();

    User.update({
        name: 'zs'
    },{
        where: {
            id: 2
        }
    })

    // 7.删除数据
    // await u.destroy();
    User.destroy({
        where: {
            id: 3
        }
    });
})();

七 条件查询

// 1.导入Sequelize
const Sequelize = require('sequelize');

(async ()=>{
    // 2.配置连接信息
    /*
    第一个参数: 要操作的数据库名称
    第二个参数: 数据库用户名
    第三个参数: 数据库密码
    第四个参数: 其它的配置信息
    * */
    const sequelize = new Sequelize('day17', 'root', 'root', {
        host: '127.0.0.1', // MySQL服务器地址
        port: 3306, // MySQL服务器端口号
        // 注意点: Sequelize不仅仅能操作MySQL还能够操作其它类型的数据库
        dialect: 'mysql', // 告诉Sequelize当前要操作的数据库类型
        pool: {
            max: 5, // 最多有多少个连接
            min: 0, // 最少有多少个连接
            idle: 10000, // 当前连接多久没有操作就断开
            acquire: 30000, // 多久没有获取到连接就断开
        }
    });

    // 3.创建模型
    let User = sequelize.define('user', {
        id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: Sequelize.STRING, // varchar(255)
            allowNull: false,
            unique: true
        },
        age: {
            type: Sequelize.TINYINT,
            defaultValue: 66
        },
        gender: {
            type: Sequelize.ENUM(['男', '女', '妖']),
            defaultValue: '妖'
        }
    }, {
        freezeTableName: true, // 告诉sequelize不需要自动将表名变成复数
        // tableName: 'student', // 自定义表名
        timestamps: false, // 不需要自动创建createAt/updateAt这两个字段
        indexes: [ // 指定索引
            {
                name: 'idx_age', // 索引名称
                fields: ['age'], // 索引字段名称
            }
        ]
    });
    // sequelize.sync();

    // 4.查询
    // 4.1查询多条数据
    // let us = await User.findAll();
    // console.log(us);
    // console.log(us.map(u => u.dataValues));

    //4.2查询指定列数据
    // let us = await User.findAll({
    //     attributes: ['name', 'age']
    // });
    // console.log(us.map(u => u.dataValues));

    // 4.3条件查询
    let us = await User.findAll({
        where: {
            // id: 1
            // age: {
            //     [Sequelize.Op.gte] : 33
            // },
            // id: 7
            [Sequelize.Op.or]: {
                age: 33,
                id: 7
            }
        }
    });
    console.log(us.map(u => u.dataValues));
})();

八 分页和排序

// 1.导入Sequelize
const Sequelize = require('sequelize');

(async ()=>{
    // 2.配置连接信息
    /*
    第一个参数: 要操作的数据库名称
    第二个参数: 数据库用户名
    第三个参数: 数据库密码
    第四个参数: 其它的配置信息
    * */
    const sequelize = new Sequelize('day17', 'root', 'root', {
        host: '127.0.0.1', // MySQL服务器地址
        port: 3306, // MySQL服务器端口号
        // 注意点: Sequelize不仅仅能操作MySQL还能够操作其它类型的数据库
        dialect: 'mysql', // 告诉Sequelize当前要操作的数据库类型
        pool: {
            max: 5, // 最多有多少个连接
            min: 0, // 最少有多少个连接
            idle: 10000, // 当前连接多久没有操作就断开
            acquire: 30000, // 多久没有获取到连接就断开
        }
    });

    // 3.创建模型
    let User = sequelize.define('user', {
        id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: Sequelize.STRING, // varchar(255)
            allowNull: false,
            unique: true
        },
        age: {
            type: Sequelize.TINYINT,
            defaultValue: 66
        },
        gender: {
            type: Sequelize.ENUM(['男', '女', '妖']),
            defaultValue: '妖'
        }
    }, {
        freezeTableName: true, // 告诉sequelize不需要自动将表名变成复数
        // tableName: 'student', // 自定义表名
        timestamps: false, // 不需要自动创建createAt/updateAt这两个字段
        indexes: [ // 指定索引
            {
                name: 'idx_age', // 索引名称
                fields: ['age'], // 索引字段名称
            }
        ]
    });
    // sequelize.sync();

    // 4.分页
    // let us = await User.findAll({
    //     offset: 2 // 跳过多少条数据
    // });
    // console.log(us.map(u => u.dataValues));

    // let us = await User.findAll({
    //     limit: 2 // 取多少条数据
    // });
    // console.log(us.map(u => u.dataValues));

    // let us = await User.findAll({
    //     offset: 2, // 跳过多少条数据
    //     limit: 2 // 取多少条数据
    // });
    // console.log(us.map(u => u.dataValues));

    // 5.排序
    let us = await User.findAll({
        order: [
            // ['id', 'desc']
            ['age', 'desc'],
            ['id', 'desc']
        ]
    });
    console.log(us.map(u => u.dataValues));
})();

九 关联查询一(一对一)

// 1.导入Sequelize
const Sequelize = require('sequelize');

(async ()=>{
    // 2.配置连接信息
    /*
    第一个参数: 要操作的数据库名称
    第二个参数: 数据库用户名
    第三个参数: 数据库密码
    第四个参数: 其它的配置信息
    * */
    const sequelize = new Sequelize('day17', 'root', 'root', {
        host: '127.0.0.1', // MySQL服务器地址
        port: 3306, // MySQL服务器端口号
        // 注意点: Sequelize不仅仅能操作MySQL还能够操作其它类型的数据库
        dialect: 'mysql', // 告诉Sequelize当前要操作的数据库类型
        pool: {
            max: 5, // 最多有多少个连接
            min: 0, // 最少有多少个连接
            idle: 10000, // 当前连接多久没有操作就断开
            acquire: 30000, // 多久没有获取到连接就断开
        }
    });

    // 3.创建模型
    let User = sequelize.define('user', {
        id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: Sequelize.STRING, // varchar(255)
            allowNull: false,
            unique: true
        },
        age: {
            type: Sequelize.TINYINT,
            defaultValue: 66
        },
        gender: {
            type: Sequelize.ENUM(['男', '女', '妖']),
            defaultValue: '妖'
        }
    }, {
        freezeTableName: true, // 告诉sequelize不需要自动将表名变成复数
        // tableName: 'student', // 自定义表名
        timestamps: false // 不需要自动创建createAt/updateAt这两个字段
    });

    let Book = sequelize.define('book', {
        id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: Sequelize.STRING, // varchar(255)
            allowNull: false,
            unique: true
        },
        price: {
            type: Sequelize.DOUBLE,
            defaultValue: 66
        },
        uId: {
            type: Sequelize.INTEGER,
            allowNull: false
        }
    }, {
        freezeTableName: true, // 告诉sequelize不需要自动将表名变成复数
        // tableName: 'student', // 自定义表名
        timestamps: false // 不需要自动创建createAt/updateAt这两个字段
    });

     //sequelize.sync();
    // 4.建立查询关系
    /*
    注意点: 只要建立了人和书的关系, 那么在查询人的时候, 就可以把拥有的那本书也查询出来
            只要建立了书和人的关系, 那么在查询书的时候, 就可以把书属于哪个人也查询出来
            如果没有建立相关的关系, 那么就不能查询出相关的内容
    * */
    User.hasOne(Book, { // hasOne 谁拥有一个谁/ 一个人拥有一本书
        foreignKey: 'uId',
        sourceKey: 'id'
    });
    Book.belongsTo(User, { // belongsTo 谁属于一个谁 / 一本书属于一个人
        foreignKey: 'uId',
        sourceKey: 'id'
    });

    // 5.关联查询
    /*
    let u = await User.findOne({
        where: {
            id: 1
        },
        // 注意点: 只要建立了表与表之间的关系, 那么在查询人的时候,就可以把这个人拥有的那本书也查询出来了
        include: {
            model: Book
        }
    });
    console.log(u.dataValues.book.dataValues);
     */
    let b = await Book.findOne({
        where: {
            id: 1
        },
        // 注意点: 只要建立了表与表之间的关系, 那么在查询书的时候,就可以把这本书属于哪一个人也查询出来了
        include: {
            model: User
        }
    });
    console.log(b.dataValues.user.dataValues);
})();

十 关联查询二(一对多)

// 1.导入Sequelize
const Sequelize = require('sequelize');

(async ()=>{
    // 2.配置连接信息
    /*
    第一个参数: 要操作的数据库名称
    第二个参数: 数据库用户名
    第三个参数: 数据库密码
    第四个参数: 其它的配置信息
    * */
    const sequelize = new Sequelize('day17', 'root', 'root', {
        host: '127.0.0.1', // MySQL服务器地址
        port: 3306, // MySQL服务器端口号
        // 注意点: Sequelize不仅仅能操作MySQL还能够操作其它类型的数据库
        dialect: 'mysql', // 告诉Sequelize当前要操作的数据库类型
        pool: {
            max: 5, // 最多有多少个连接
            min: 0, // 最少有多少个连接
            idle: 10000, // 当前连接多久没有操作就断开
            acquire: 30000, // 多久没有获取到连接就断开
        }
    });

    // 3.创建模型
    let User = sequelize.define('user', {
        id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: Sequelize.STRING, // varchar(255)
            allowNull: false,
            unique: true
        },
        age: {
            type: Sequelize.TINYINT,
            defaultValue: 66
        },
        gender: {
            type: Sequelize.ENUM(['男', '女', '妖']),
            defaultValue: '妖'
        }
    }, {
        freezeTableName: true, // 告诉sequelize不需要自动将表名变成复数
        // tableName: 'student', // 自定义表名
        timestamps: false // 不需要自动创建createAt/updateAt这两个字段
    });

    let Book = sequelize.define('book', {
        id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: Sequelize.STRING, // varchar(255)
            allowNull: false,
        },
        price: {
            type: Sequelize.DOUBLE,
            defaultValue: 66
        },
        uId: {
            type: Sequelize.INTEGER,
            allowNull: false
        }
    }, {
        freezeTableName: true, // 告诉sequelize不需要自动将表名变成复数
        // tableName: 'student', // 自定义表名
        timestamps: false // 不需要自动创建createAt/updateAt这两个字段
    });

    // sequelize.sync();
    // 4.建立查询关系
    User.hasMany(Book, { // 一个人拥有多本书
        foreignKey: 'uId',
        sourceKey: 'id'
    });
    Book.belongsTo(User, { // 一本书属于一个人
        foreignKey: 'uId',
        sourceKey: 'id'
    })
    // 5.关联查询
    /*
    let u = await User.findOne({
        where: {
            id: 1
        },
        include: {
            model: Book
        }
    });
    console.log(u.dataValues.books.map(b=>b.dataValues));
     */
    let b = await Book.findOne({
        where: {
            id: 3
        },
        include: {
            model: User
        }
    });
    console.log(b.dataValues.user.dataValues);
})();

十一 建立表关系的另一种方式

// 1.导入Sequelize
const Sequelize = require('sequelize');

(async ()=>{
    // 2.配置连接信息
    /*
    第一个参数: 要操作的数据库名称
    第二个参数: 数据库用户名
    第三个参数: 数据库密码
    第四个参数: 其它的配置信息
    * */
    const sequelize = new Sequelize('demo', 'root', 'root', {
        host: '127.0.0.1', // MySQL服务器地址
        port: 3306, // MySQL服务器端口号
        // 注意点: Sequelize不仅仅能操作MySQL还能够操作其它类型的数据库
        dialect: 'mysql', // 告诉Sequelize当前要操作的数据库类型
        pool: {
            max: 5, // 最多有多少个连接
            min: 0, // 最少有多少个连接
            idle: 10000, // 当前连接多久没有操作就断开
            acquire: 30000, // 多久没有获取到连接就断开
        }
    });


    // 3.创建模型
    let User = sequelize.define('user', {
        id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: Sequelize.STRING, // varchar(255)
            allowNull: false,
            unique: true
        },
        age: {
            type: Sequelize.TINYINT,
            defaultValue: 66
        },
        gender: {
            type: Sequelize.ENUM(['男', '女', '妖']),
            defaultValue: '妖'
        }
    }, {
        freezeTableName: true, // 告诉sequelize不需要自动将表名变成复数
        // tableName: 'student', // 自定义表名
        timestamps: false // 不需要自动创建createAt/updateAt这两个字段
    });

    let Book = sequelize.define('book', {
        id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: Sequelize.STRING, // varchar(255)
            allowNull: false,
        },
        price: {
            type: Sequelize.DOUBLE,
            defaultValue: 66
        },
        userId: {
            type: Sequelize.INTEGER,
            allowNull: false,
            references: {
                model: User,
                key: 'id'
            }
        }
    }, {
        freezeTableName: true, // 告诉sequelize不需要自动将表名变成复数
        // tableName: 'student', // 自定义表名
        timestamps: false // 不需要自动创建createAt/updateAt这两个字段
    });

    // 4.建立查询关系
    /*
    User.hasMany(Book, { // 一个人拥有多本书
        foreignKey: 'uId',
        sourceKey: 'id'
    });
    Book.belongsTo(User, { // 一本书属于一个人
        foreignKey: 'uId',
        sourceKey: 'id'
    });
     */
    User.hasMany(Book);
    Book.belongsTo(User);
    // 注意点: 想要sequelize自动创建外键, 那么就必须在写完上述的两句代码之后再执行同步方法, 才会自动创建对应的外键
    sequelize.sync();

    // 5.关联查询
    /*
    let u = await User.findOne({
        where: {
            id: 1
        },
        include: {
            model: Book
        }
    });
    console.log(u.dataValues.books.map(b=>b.dataValues));
     */
    /*
    let b = await Book.findOne({
        where: {
            id: 3
        },
        include: {
            model: User
        }
    });
    console.log(b.dataValues.user.dataValues);
     */
})();

十二 关联查询三(多对多)

// 1.导入Sequelize
const Sequelize = require('sequelize');

(async ()=>{
    // 2.配置连接信息
    /*
    第一个参数: 要操作的数据库名称
    第二个参数: 数据库用户名
    第三个参数: 数据库密码
    第四个参数: 其它的配置信息
    * */
    const sequelize = new Sequelize('demo', 'root', 'root', {
        host: '127.0.0.1', // MySQL服务器地址
        port: 3306, // MySQL服务器端口号
        // 注意点: Sequelize不仅仅能操作MySQL还能够操作其它类型的数据库
        dialect: 'mysql', // 告诉Sequelize当前要操作的数据库类型
        pool: {
            max: 5, // 最多有多少个连接
            min: 0, // 最少有多少个连接
            idle: 10000, // 当前连接多久没有操作就断开
            acquire: 30000, // 多久没有获取到连接就断开
        }
    });


    // 3.创建模型
    let Student = sequelize.define('student', {
        id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: Sequelize.STRING, // varchar(255)
            allowNull: false,
            unique: true
        }
    }, {
        freezeTableName: true, // 告诉sequelize不需要自动将表名变成复数
        // tableName: 'student', // 自定义表名
        timestamps: false // 不需要自动创建createAt/updateAt这两个字段
    });

    let Teacher = sequelize.define('teacher', {
        id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: Sequelize.STRING, // varchar(255)
            allowNull: false,
            unique: true
        }
    }, {
        freezeTableName: true, // 告诉sequelize不需要自动将表名变成复数
        // tableName: 'student', // 自定义表名
        timestamps: false // 不需要自动创建createAt/updateAt这两个字段
    });

    let Relation = sequelize.define('relation', {
        studentId: {
            type: Sequelize.INTEGER,
            allowNull: false,
            references: {
                model: Student,
                key: 'id'
            }
        },
        teacherId: {
            type: Sequelize.INTEGER,
            allowNull: false,
            references: {
                model: Student,
                key: 'id'
            }
        }
    }, {
        freezeTableName: true, // 告诉sequelize不需要自动将表名变成复数
        // tableName: 'student', // 自定义表名
        timestamps: false // 不需要自动创建createAt/updateAt这两个字段
    });
    // 4.建立查询关系
    Student.belongsToMany(Teacher, { // 一个学生属于多个老师
        through: Relation
    });
    Teacher.belongsToMany(Student, { // 一个老师属于多个学生
        through: Relation
    });

    sequelize.sync();
    // 5.关联查询
    /*
    let s = await Student.findOne({
        where: {
            id: 1
        },
        include: {
            model: Teacher
        }
    });
    console.log(s.dataValues.teachers.map(t=>t.dataValues));
     */
    let t = await Teacher.findOne({
        where: {
            id: 1
        },
        include: {
            model: Student
        }
    });
    console.log(t);
})();

 

上一篇:建立Model


下一篇:node.js后端之sequelize