Eggjs快速入门2:egg操作mysql和redis数据库

1,873 阅读4分钟

这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」。

egg+mysql

框架提供了 egg-mysql 插件来访问 MySQL 数据库。这个插件既可以访问普通的 MySQL 数据库,也可以访问基于 MySQL 协议的在线数据库服务。

1.连接mysql

安装mysql2,egg-mysql

npm i mysql2 egg-mysql

在plugin.js中打开egg-mysql插件

//配置mysql内容
exports.mysql = {
  enable: true, // 开启
  package: "egg-mysql", // 对应哪个包
};

在config.default.js配置连接mysql的参数(具体参见官方文档),以下配置够用即可

  config.mysql = {
    client: {
      // host
      host: "xxxxxxIP地址(本地127.0.0.1)",
      // 端口号
      port: "3306",
      // 用户名
      user: "root",
      // 密码
      password: "123456",
      // 数据库名
      database: "database1",
    },
    // 是否加载到 app 上,默认开启
    app: true,
    // 是否加载到 agent 上,默认关闭
    agent: false,
  };

这个时候this.app.mysql就能链接到mysql的对象了

2.使用egg操作mysql的方法

create

// 插入
const result = await this.app.mysql.insert('posts', { title: 'Hello World' }); // 在 post 表中,插入 title 为 Hello World 的记录

=> INSERT INTO `posts`(`title`) VALUES('Hello World');

read

查询某一个数据使用get,和下面说到的select区别是,不过你根据条件查出来有多少,都只会选择第一个

const post = await this.app.mysql.get('posts', { id: 12 });
=> SELECT * FROM `posts` WHERE `id` = 12 LIMIT 0, 1;

使用select查询,里面可以使用where条件,cloumns查询出来的表字段,order排序方式,limit,offet用于分页处理的数据量和偏移量

const results = await this.app.mysql.select('posts', { // 搜索 post 表
  where: { status: 'draft', author: ['author1', 'author2'] }, // WHERE 条件
  columns: ['author', 'title'], // 要查询的表字段
  orders: [['created_at','desc'], ['id','desc']], // 排序方式
  limit: 10, // 返回数据量
  offset: 0, // 数据偏移量
});
=> SELECT `author`, `title` FROM `posts`
  WHERE `status` = 'draft' AND `author` IN('author1','author2')
  ORDER BY `created_at` DESC, `id` DESC LIMIT 0, 10;

update

更新很简单,根据主键查询出来需要更新的数据,然后将需要更新的数据进行表数据替换。默认主键是id,如果不是id需要多加一个参数手动指定一下主键。

// 修改数据,将会根据主键 ID 查找,并更新
const row = {
  id: 123,
  name: 'fengmk2',
  otherField: 'other field value',    // any other fields u want to update
  modifiedAt: this.app.mysql.literals.now, // `now()` on db server
};
const result = await this.app.mysql.update('posts', row); // 更新 posts 表中的记录

=> UPDATE `posts` SET `name` = 'fengmk2', `modifiedAt` = NOW() WHERE id = 123 ;

delete

删除就直接使用delete配合表,查询条件进行操作进行了。

const result = await this.app.mysql.delete('posts', {
  author: 'fengmk2',
});

=> DELETE FROM `posts` WHERE `author` = 'fengmk2';

3.直接执行sql语句(容易sql注入,正规项目不建议)

插件本身也支持拼接与直接执行 sql 语句。使用 query 可以执行合法的 sql 语句。 极其不建议开发者拼接 sql 语句,这样很容易引起 sql 注入!!

const postId = 1;
const results = await this.app.mysql.query('update posts set hits = (hits + ?) where id = ?', [1, postId]);

=> update posts set hits = (hits + 1) where id = 1;

4.事务处理

用于同时修改多张表,比如支付数据我可能要把购物车的商品表清除,支付数据表增加,但是支付失败后,要还原清除的购物车商品表,所以必须使用事务

手动控制

const conn = await app.mysql.beginTransaction(); // 初始化事务

try {
  await conn.insert(table, row1);  // 第一步操作
  await conn.update(table, row2);  // 第二步操作
  await conn.commit(); // 提交事务
} catch (err) {
  // error, rollback
  await conn.rollback(); // 一定记得捕获异常后回滚事务!!
  throw err;
}

自动控制(推荐)

const result = await app.mysql.beginTransactionScope(async conn => {
  // don't commit or rollback by yourself
  await conn.insert(table, row1);
  await conn.update(table, row2);
  return { success: true };
}, ctx); // ctx 是当前请求的上下文,如果是在 service 文件中,可以从 `this.ctx` 获取到
// if error throw on scope, will auto rollback

源码就没有演示这么多了,挺简单一步一步来

centos+redis

1.centos安装redis

1、安装redis

yum -y install redis

2、启动和添加启动项

 systemctl start redis.service
 systemctl enable redis.service // 开机自启动

3、查看进程是否已经启动

ps -ef | grep redis

4、修改配置文件

/etc/redis.conf

5、注释掉这行,重启外网访问 bind 127.0.0.1

6、这个时候egg连接还是有问题,因为无密码,无本地ip和外网ip映射,触发了protectmode保护模式。还要将配置文件的mode模式更改为yes

7、重启服务

systemctl restart redis.service

8、注意服务器开放外网防火墙6379端口,不然会超时

9、redis支持设置密码

$vim /etc/redis/redis.conf
 
requirepass xxxxxxxxxx  // xxxxxxxxxx is your password

2.Egg连接Redis

npm install egg-redis --save

//plugin.js 打开插件
exports.redis = {
  enable: true,
  package: 'egg-redis',
};

//config.default.js 配置插件
  config.redis = {
    client: {
      port: 6379,          // Redis port
      host: '127.0.0.1',   // Redis host
      password: '',
      db: 0
    }
  }

配置多连接池,egg-redis提供了多连接池的功能,业务需求中如果需要配置多个redis服务器可以参考。

config.redis = {
  clients: {
    foo: {                
      port: 6379,          // Redis port
      host: '127.0.0.1',   // Redis host
      password: 'auth',
      db: 0,
    },
    bar: {
      port: 6379,
      host: '127.0.0.1',
      password: 'auth',
      db: 1,
    },
  }
}

Egg.js+Redis的使用

简单使用,在业务上用途比如要做一个缓存一张试卷5分钟,用途退出去5分钟还可以缓存在服务器

// app/controller/home.js
 
module.exports = app => {
  return class HomeController extends app.Controller {
    async index() {
      const { ctx, app } = this;
      // set
      await app.redis.set('foo', 'bar');
      // get
      ctx.body = await app.redis.get('foo');
    }
  };
};

更多redis的操作可以参照redis官网的api,我这边主要是做了简单的存取 参照网上进行封装成一个service,进行存取方法的控制,比原生的get,set更加完善一点。