Koa 中使用 Sqlite3 和 Sequelize6.x 入门教程

前言

SQLite 是一种嵌入式数据库,它的数据库就是一个文件。

Sequelize 是一个基于 promise 的 Node.js ORM, 目前支持 Postgres, MySQL, MariaDB, SQLite 以及 Microsoft SQL Server. 它具有强大的事务支持, 关联关系, 预读和延迟加载,读取复制等功能.

基于 Sqlite3 的项目,直接是用 Sequelize 进行对象和表的映射。

环境配置

// 安装
npm i sequelize sqlite3 -S

// sequelize 5.x <=== 注意版本,6.x 有更改
// sqlite3 5.x

项目结构

image-20200623105249938

配置文件夹 config

// config/config.js
const path = require('path')
const sqlite3 = require('sqlite3').verbose()
module.exports = {
  test: {
    storage: path.join(__dirname, '../db/db_test.sqlite'), // 文件路径
    host: 'localhost', // 地址
    dialect: 'sqlite', // 目标数据库种类
    dialectModule: sqlite3
    logging: console.log,
  }
}

注意:sqlite 可以忽略密码。(PS:使用密码可能会无法创建 sqlite 文件)

在 window 中需要手动引入 sqlite3 否则会找不到。

模型文件夹 models

该文件夹中 index.js 入口文件,链接数据库。

// models/index.js
const fs = require('fs')
const path = require('path') 
const basename = path.basename(__filename) // 当前文件名
const Sequelize = require('sequelize')
const config = require('../config/config') // 配置文件
const sequelize = new Sequelize(config.test) // sqlite: 前三个参数传 undefined。

const db = {}
// 引入其他的Model文件。
fs.readdirSync(__dirname)
	// 过滤:不是index.js, 含有.、以 .js 结尾的文件
  .filter(file => (file.indexOf('.' !== 0) && (file !== basename) && (file.slice(-3) === '.js')))
  .forEach(file => {
  	// 引入所有的Model文件
  	// 采用 import 引入
	const model = sequelize.import(path.join(__dirname, file)) // 在 6.x 中移除 import 。
    db[model.name] = model
  })
// 关联配置
Object.keys(db).forEach(modelName => {
  if (db[modelName].associate) {
    db[modelName].associate(db)
  }
})

db.sequelize = sequelize
db.Sequelize = Sequelize
module.exports = db

注意:sequelize6.x 开始移除 .import 方法。

升级:

sequelize.js 文件配置数据库.

const Sequelize = require('sequelize')
const config = require('../../config/config')
const sequelize = new Sequelize(config.dangjian)
sequelize
  .authenticate()
  .then(() => {
    console.log('Connection has been established successfully.')
  })
  .catch(err => {
    console.error('Unable to connect to the database:', err)
  })

sequelize.sync({ force: false })

module.exports = sequelize

index.js 文件负责整合模型。

const fs = require('fs')
const path = require('path')
const basename = path.basename(__filename) // index.js
const db = {}

fs.readdirSync(__dirname)
  .filter(
    file =>
      file.indexOf('.' !== 0) && file !== basename && file.slice(-3) === '.js'
  )
  .forEach(file => {
    const model = require(`./${file}`)
    const name = file.split('.')[0]
    db[name] = model
  })

module.exports = db

模型文件 User

sequelize5.x

// models/user.js
module.exports = (sequelize, DataTypes) => {
  // 参数一:modelName: user
  // 参数二:定义属性
  // 参数三:其他配置 https://sequelize.org/master/class/lib/model.js~Model.html#static-method-init
  const User = sequelize.define('user', {
    name: {
      type: DataTypes.STRING,
      allowNull: false
    },
    age: {
      type: DataTypes.INTEGER,
      defaultValue: 0
    },
    gender: {
      type: DataTypes.ENUM,
      values: ['男', '女', '未知'],
      defaultValue: '未知'
    }
  }, {
    tableName: 'user'
  })
  User.associate = models => {
    // 定义关联
  }
  return User
}

参考:其他配置:options

升级

const { DataTypes } = require('sequelize')
const sequelize = require('./sequelize')

const User = sequelize.define('user', {
	name: {
      type: DataTypes.STRING,
      allowNull: false
    },
    age: {
      type: DataTypes.INTEGER,
      defaultValue: 0
    },
    gender: {
      type: DataTypes.ENUM,
      values: ['男', '女', '未知'],
      defaultValue: '未知'
    }
})

module.exports = User

知识点

分页查询

// controller/UserCtl.js
class UserCtl {
  /**
   * 获取所有用户
   * @param {Object} ctx 
   */
  async index(ctx) {
    // 分页 page, pageSize
    // 使用 findAndCountAll 代替 findAll
    const { page = 1, pageSize = 10 } = ctx.request.body
    // 偏移量
    let offset = (page - 1) * pageSize
    try {    
      const {count, rows} = await db.user.findAndCountAll({
        limit: parseInt(pageSize), // 页容量
        offset: offset, // 偏移量
      })
      const data = {
        code: 0,
        msg: 'success',
        totalCount: count,
        data: rows,
      }
      ctx.ok(data)
    } catch (error) {
      const data = {
        code: 1,
        msg: '服务错误~',
        err: error.name
      }
      ctx.badRequest(data)
    }
  }
}

API文档:findAndCountAll

findAndCountAllfindAll 区别。返回结果不同:前者返回 Promise<{count: number, rows: Model[]}>,count 对象总数,rows本次查到的对象数组。后者直接返回对象数组。

有人遇到个错误:分页总数计算错误问题 (PS:暂时还没有遇到)

参考

Sequelize API

Sequelize中文文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

繁华落尽Owenlee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值