项目作者: eggjs

项目描述 :
MySQL plugin for egg
高级语言: JavaScript
项目地址: git://github.com/eggjs/egg-mysql.git
创建时间: 2016-08-26T07:20:17Z
项目社区:https://github.com/eggjs/egg-mysql

开源协议:MIT License

下载


@eggjs/mysql

@eggjs/mysql"">NPM version
CI
Test coverage
@eggjs/mysql"">npm download
Node.js Version
PRs Welcome
CodeRabbit Pull Request Reviews

MySQL plugin for Egg.js

Install

  1. npm i @eggjs/mysql

MySQL Plugin for egg@4, support egg application access to MySQL database.

If you’re using egg@3, please use egg-mysql@5 instead.

This plugin based on @eggjs/rds, if you want to know specific usage, you should refer to the document of @eggjs/rds.

Configuration

Change ${app_root}/config/plugin.ts to enable MySQL plugin:

  1. export default {
  2. mysql: {
  3. enable: true,
  4. package: '@eggjs/mysql',
  5. },
  6. };

Configure database information in ${app_root}/config/config.default.ts:

Simple database instance

  1. export default {
  2. mysql: {
  3. // database configuration
  4. client: {
  5. // host
  6. host: 'mysql.com',
  7. // port
  8. port: '3306',
  9. // username
  10. user: 'test_user',
  11. // password
  12. password: 'test_password',
  13. // database
  14. database: 'test',
  15. },
  16. // load into app, default is `true`
  17. app: true,
  18. // load into agent, default is `false`
  19. agent: false,
  20. },
  21. };

Usage:

  1. await app.mysql.query(sql, values); // you can access to simple database instance by using app.mysql.

Multiple database instance

  1. export default {
  2. mysql: {
  3. clients: {
  4. // clientId, access the client instance by app.mysql.get('clientId')
  5. db1: {
  6. // host
  7. host: 'mysql.com',
  8. // port
  9. port: '3306',
  10. // username
  11. user: 'test_user',
  12. // password
  13. password: 'test_password',
  14. // database
  15. database: 'test',
  16. },
  17. // ...
  18. },
  19. // default configuration for all databases
  20. default: {},
  21. // load into app, default is open
  22. app: true,
  23. // load into agent, default is close
  24. agent: false,
  25. },
  26. };

Usage:

  1. const client1 = app.mysqls.getSingletonInstance('db1');
  2. await client1.query(sql, values);
  3. const client2 = app.mysqls.getSingletonInstance('db2');
  4. await client2.query(sql, values);

CRUD user guide

Create

  1. // insert
  2. const result = await app.mysql.insert('posts', { title: 'Hello World' });
  3. const insertSuccess = result.affectedRows === 1;

Read

  1. // get
  2. const post = await app.mysql.get('posts', { id: 12 });
  3. // query
  4. const results = await app.mysql.select('posts', {
  5. where: { status: 'draft' },
  6. orders: [
  7. ['created_at', 'desc'],
  8. ['id', 'desc'],
  9. ],
  10. limit: 10,
  11. offset: 0,
  12. });

Update

  1. // update by primary key ID, and refresh
  2. const row = {
  3. id: 123,
  4. name: 'fengmk2',
  5. otherField: 'other field value',
  6. modifiedAt: app.mysql.literals.now, // `now()` on db server
  7. };
  8. const result = await app.mysql.update('posts', row);
  9. const updateSuccess = result.affectedRows === 1;

Delete

  1. const result = await app.mysql.delete('table-name', {
  2. name: 'fengmk2',
  3. });

Transaction

Manual control

  • adventage: beginTransaction, commit or rollback can be completely under control by developer
  • disadventage: more handwritten code, Forgot catching error or cleanup will lead to serious bug.
  1. const conn = await app.mysql.beginTransaction();
  2. try {
  3. await conn.insert(table, row1);
  4. await conn.update(table, row2);
  5. await conn.commit();
  6. } catch (err) {
  7. // error, rollback
  8. await conn.rollback(); // rollback call won't throw err
  9. throw err;
  10. }

Automatic control: Transaction with scope

  • API:async beginTransactionScope(scope, ctx)
    • scope: A generatorFunction which will execute all sqls of this transaction.
    • ctx: The context object of current request, it will ensures that even in the case of a nested transaction, there is only one active transaction in a request at the same time.
  • adventage: easy to use, as if there is no transaction in your code.
  • disadvantage: all transation will be successful or failed, cannot control precisely
  1. const result = await app.mysql.beginTransactionScope(async conn => {
  2. // don't commit or rollback by yourself
  3. await conn.insert(table, row1);
  4. await conn.update(table, row2);
  5. return { success: true };
  6. }, ctx); // ctx is the context of current request, access by `this.ctx`.
  7. // if error throw on scope, will auto rollback

Advance

Custom SQL splicing

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

Literal

If you want to call literals or functions in mysql , you can use Literal.

Inner Literal

  • NOW(): The database system time, you can obtain by app.mysql.literals.now.
  1. await app.mysql.insert(table, {
  2. create_time: app.mysql.literals.now,
  3. });
  4. // INSERT INTO `$table`(`create_time`) VALUES(NOW())

Custom literal

The following demo showed how to call CONCAT(s1, ...sn) function in mysql to do string splicing.

  1. const Literal = app.mysql.literals.Literal;
  2. const first = 'James';
  3. const last = 'Bond';
  4. await app.mysql.insert(table, {
  5. id: 123,
  6. fullname: new Literal(`CONCAT("${first}", "${last}"`),
  7. });
  8. // INSERT INTO `$table`(`id`, `fullname`) VALUES(123, CONCAT("James", "Bond"))

For the local dev

Run docker compose to start test mysql service

  1. docker compose -f docker-compose.yml up -d
  2. # if you run the first time, should wait for ~20s to let mysql service init started

Run the unit tests

  1. npm test

Stop test mysql service

  1. docker compose -f docker-compose.yml down

Questions & Suggestions

Please open an issue here.

License

MIT

Contributors

Contributors

Made with contributors-img.