49

Koa使用Sqlite3和Sequelize

 4 years ago
source link: https://blog.itlee.top/2020/07/13/Koa使用Sqlite3和Sequelize/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

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

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

环境配置

// 安装
npm i sequelize sqlite3 -S

项目结构

Y3mYna2.jpg!web

配置文件夹 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(undefined, undefined, undefined, 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))
    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

模型文件 User

// 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

知识点

分页

// 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:暂时还没有遇到)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK