MySQL
MySQL is one of the most common and best RDBMS in terms of web applications. It is used in many large-scale websites such as Google and Facebook.
# egg-mysql
egg-mysql
is provided to access both the MySQL databases and MySQL-based online database service.
# Installation and Configuration
Install egg-mysql
$ npm i --save egg-mysql |
Enable Plugin:
// config/plugin.js |
Configure database information in config/config.${env}.js
# Single Data Source
Configuration to accesss single MySQL instance as shown below:
// config/config.${env}.js |
Use:
await app.mysql.query(sql, values); // single instance can be accessed through app.mysql |
# Multiple Data Sources
Configuration to accesss multiple MySQL instances as below:
exports.mysql = { |
Use:
const client1 = app.mysql.get('db1'); |
# Dynamic Creation
Pre-declaration of configuration might not needed in the configuration file. Obtaining the actual parameters dynamically from the configuration center then initialize an instance instead.
// {app_root}/app.js |
# Service Layer
Connecting to MySQL is a data processing layer in the Web layer. So it is strongly recommended that keeping the code in the Service layer.
An example of connecting to MySQL as follows.
Details of Service layer, refer to service
// app/service/user.js |
After that, obtaining the data from service layer using the controller
// app/controller/user.js |
# Writing CRUD
Following statments default under app/service
if not specifed
# Create
INSERT method to perform the INSERT INTO query
// INSERT |
# Read
Use get
or select
to select one or multiple records. select
method support query criteria and result customization
- get one record
const post = await this.app.mysql.get('posts', { id: 12 }); |
- query all from the table
const results = await this.app.mysql.select('posts'); |
- query criteria and result customization
const results = await this.app.mysql.select('posts', { // search posts table |
# Update
UPDATE operation to update the records of databases
// modify data and search by primary key ID, and refresh |
# Delete
DELETE operation to delete the records of databases
const result = await this.app.mysql.delete('posts', { |
# Implementation of SQL statement
Plugin supports splicing and execute SQL statment directly. It can use query
to execute a valid SQL statement
Note!! Strongly do not recommend developers splicing SQL statement, it is easier to cause SQL injection!!
Use the mysql.escape
method if you have to splice SQL statement
Refer to preventing-sql-injection-in-node-js
const postId = 1; |
# Transaction
Transaction is mainly used to deal with large data of high complexity. For example, in a personnel management system, deleting a person which need to delete the basic information of the staff, but also need to delete the related information of staff, such as mailboxes, articles and so on. It is easier to use transaction to run a set of operations. A transaction is a set of continuous database operations which performed as a single unit of work. Each individual operation within the group is successful and the transaction succeeds. If one part of the transaction fails, then the entire transaction fails. In gerenal, transaction must be atomic, consistent, isolated and durable.
- Atomicity requires that each transaction be "all or nothing": if one part of the transaction fails, then the entire transaction fails, and the database state is left unchanged.
- The consistency property ensures that any transaction will bring the database from one valid state to another.
- The isolation property ensures that the concurrent execution of transactions results in a system state that would be obtained if transactions were executed sequentially
- The durability property ensures that once a transaction has been committed, it will remain so.
Therefore, for a transaction, must be accompanied by beginTransaction, commit or rollback, respectively, beginning of the transaction, success and failure to roll back.
egg-mysql proviodes two types of transactions
# Manual Control
- adventage:
beginTransaction
,commit
orrollback
can be completely under control by developer - disadventage: more handwritten code, Forgot catching error or cleanup will lead to serious bug.
const conn = await app.mysql.beginTransaction(); // initialize the transaction |
# Automatic Control: Transaction with Scope
- API:
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
const result = await app.mysql.beginTransactionScope(async conn => { |
# Literal
Use Literal
if need to call literals or functions in MySQL
# Inner Literal
NOW()
:The database system time, obtained byapp.mysql.literals.now
await this.app.mysql.insert(table, { |
# Custom literal
The following demo showe how to call CONCAT(s1, ...sn)
funtion in mysql to do string splicing.
const Literal = this.app.mysql.literals.Literal; |