@loopback/docs
Version:
Documentation files rendered at [https://loopback.io](https://loopback.io)
314 lines (256 loc) • 8.56 kB
Markdown
lang: en
title: 'MySQL Connector Tutorial'
keywords:
LoopBack 4.0, LoopBack 4, Node.js, TypeScript, OpenAPI, Connector, MySQL,
Tutorial
sidebar: lb4_sidebar
permalink: /doc/en/lb4/Connecting-to-MySQL.html
# Connecting to MySQL
The following tutorial introduces how to set up MySQL as the data source of
LoopBack 4 applications with
[LoopBack MySQL connector](https://github.com/strongloop/loopback-connector-mysql).
## Prerequisites
Before starting this tutorial, make sure you have the following installed:
- Node.js version 10 or higher
- LoopBack 4 CLI; see
[Getting Started with LoopBack 4](../../Getting-started.md)
## Tutorial - MySQL
### 1. Create a new LoopBack 4 app
Let's use the [LB4 CLI](../../Command-line-interface.md) `lb4 app` to create a
LoopBack 4 application called `MyApp`:
```bash
$ lb4 app
? Project name: my-app
? Project description: MySQL connector tutorial
? Project root directory: my-app
? Application class name: MyAppApplication
? Select features to enable in the project (Press <space> to select, <a> to togg
le all, <i> to invert selection)
❯◉ Enable eslint: add a linter with pre-configured lint rules
◉ Enable prettier: install prettier to format code conforming to rules
◉ Enable mocha: install mocha to run tests
◉ Enable loopbackBuild: use @loopback/build helpers (e.g. lb-eslint)
◉ Enable vscode: add VSCode config files
◉ Enable docker: include Dockerfile and .dockerignore
◉ Enable repositories: include repository imports and RepositoryMixin
(Move up and down to reveal more choices)
```
### 2. Create models
Let's create a simple model `User`. To keep the tutorial short, the prompts of
`lb4 model` are skipped:
{% include code-caption.html content="user.model.ts" %}
```ts
// imports
@model()
export class User extends Entity {
@property({
type: 'number',
id: true,
generated: true,
})
id: number;
@property({
type: 'string',
})
name?: string;
@property({
type: 'boolean',
})
hasAccount: boolean;
constructor(data?: Partial<User>) {
super(data);
}
}
```
### 3. Create a data source
Next, let's create a DataSource `db` using the MySQL connector by the prompts
below:
```bash
$ lb4 datasource
? Datasource name: db
? Select the connector for db:
...
MongoDB (supported by StrongLoop)
❯ MySQL (supported by StrongLoop)
PostgreSQL (supported by StrongLoop)
...
? Connection String url to override other settings (eg: mysql://user:pass@host/db):
? host: localhost
? port: 3306
? user: loopback
? password: [hidden] // example password: pa55w0rd
? database: demo
Datasource Db was created in src/datasources/
```
Under `src/datasources/db.datasource.ts`, we can find the `DbDataSource` class
and the config we just set:
```ts
const config = {
name: 'db',
connector: 'mysql',
url: '',
host: 'localhost',
port: 3306,
user: 'loopback',
password: 'pa55w0rd',
database: 'demo',
};
```
### 4. Create repositories
A [Repository](../../Repository.md) is an artifact that ties the model and the
datasource. We will need to create the repository for the `User` class to access
the database. The steps of creating `UserRepository` by running `lb4 repository`
are skipped here:
{% include code-caption.html content="user.repository.ts" %}
```ts
// imports
export class UserRepository extends DefaultCrudRepository<
User,
typeof User.prototype.id,
UserRelations
> {
constructor(@inject('datasources.db') dataSource: DbDataSource) {
super(User, dataSource);
}
}
```
### 5. Database migration
LoopBack provides a convenient way to create schemas/tables for our models if we
don't have corresponding schemas defined in the relational database. Once we
created the above artifacts, run the following commands:
**1.** Build the project:
```bash
$ npm run build
```
**2.** Migrate database schemas (alter existing tables):
```bash
$ npm run migrate
```
This would generate the corresponding MySQL table `User` using the metadata from
`User` model via auto-migrate if it does not exist. See
[Database Migration](#database-migration) section below for information.
If you check the database, you should able to see the table `User`.
```
mysql> describe User;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(512) | YES | | NULL | |
| hasAccount | tinyint(1) | YES | | NULL | |
+------------+--------------+------+-----+---------+----------------+
```
### 6. Create endpoints and view data using API Explorer
Once we built a [controller](../../Controller.md) with `lb4 controller` to
handle requests:
```bash
$ lb4 controller
? Controller class name: user
Controller User will be created in src/controllers/user.controller.ts
? What kind of controller would you like to generate? REST Controller with CRUD
functions
? What is the name of the model to use with this CRUD repository? User
? What is the name of your CRUD repository? UserRepository
? What is the name of ID property? id
? What is the type of your ID? number
? Is the id omitted when creating a new instance? Yes
? What is the base HTTP path name of the CRUD operations? /users
```
Notice that the id is omitted in the request here because it is autogenerated.
From the project root, start the app:
```bash
$ npm start
```
We can verify what we just created with API Explorer
[http://localhost:3000/explorer/](http://localhost:3000/explorer/).
## Database Migration
As we showed in the previous steps,
[Database migration](../../Database-migrations.md) helps you create relational
database schemas based on definitions of your models. Here are some tips:
- if you make further changes to models, make sure to run `npm run build` before
running the migrate script again
- `npm run migrate` alters existing tables for you. If you'd like to drop any
existing schemas, you can do `npm run migrate -- --rebuild`. But notice that
all the data will be lost.
Please check [Database migration](../../Database-migrations.md) for details.
Besides the basic model metadata, you can also specify part of the database
schema definition via the property definition, which would be mapped to the
database. See
[Data Mapping Properties](https://loopback.io/doc/en/lb4/MySQL-connector.html#data-mapping-properties).
## Model Discovery
While database migration allows you to migrate models to the DB, LoopBack also
provides a command [`lb4 discover`](../../Discovering-models.md) to generate
models based on schemas from the database. For example, we can try to discover
the `user` table we created previously:
```bash
$ npm run build
$ lb4 discover --schema demo
? Select the connector to discover db
? Select the models which to discover User
? Select a convention to convert db column names(EXAMPLE_COLUMN) to model proper
ty names: Camel case (exampleColumn) (Recommended)
? Overwrite src/models/user.model.ts? overwrite
force src/models/user.model.ts
update src/models/index.ts
Models User was created in src/models/
```
As we can see, the newly generated `User` model would contain database specific
details:
```ts
// imports
@model({
settings: {idInjection: false, mysql: {schema: 'testdb', table: 'User'}},
})
export class User extends Entity {
@property({
type: 'number',
required: true, // set this to false if the value is auto-generated by the db
precision: 10,
scale: 0,
id: 1,
mysql: {
columnName: 'id',
dataType: 'int',
dataLength: null,
dataPrecision: 10,
dataScale: 0,
nullable: 'N',
},
})
id: number;
@property({
type: 'string',
length: 512,
mysql: {
columnName: 'name',
dataType: 'varchar',
dataLength: 512,
dataPrecision: null,
dataScale: null,
nullable: 'Y',
},
})
name?: string;
@property({
type: 'number',
precision: 3,
scale: 0,
mysql: {
columnName: 'hasAccount',
dataType: 'tinyint',
dataLength: null,
dataPrecision: 3,
dataScale: 0,
nullable: 'Y',
},
})
hasAccount?: number;
// ...
}
```
The field `mysql.<property>` maps to the database definition of a table/column.
See
[Data Mapping Properties](https://loopback.io/doc/en/lb4/MySQL-connector.html#data-mapping-properties)
for details.