スキップしてメイン コンテンツに移動

[PostgreSQL] Play with TypeORM 1

Intro

This time, I tried accessing Database by TypeORM. Because I wanted to manage Database tables by ORM, I created a table first. 

TypeORM - Amazing ORM for TypeScript and JavaScript (ES7, ES6, ES5).

Installation and creating a project

Installation

TypeORM needed "reflect-metadata" and database driver.
npm install --save typeorm reflect-metadata pg typescript tsc
npm install --save-dev @types/node
And I also installed "ts-node" to skip compiling.
npm install --save ts-node

Preparing

References

I could generate a TypeORM project by TypeORM command.
npx typeorm init --name gen-typeorm-sample --database postgres
I refered Most of all settings from it.

Adding files and folders

First, I added tsconfig.json.
npx tsc --init
And I edited like below.

tsconfig.json


{
  "compilerOptions": {
    /* Basic Options */
    "incremental": true,
    "target": "es5",
    "module": "commonjs",
    "lib": [
      "es5",
      "es6"
    ],
    "sourceMap": true,
    "outDir": "./build",
    /* Strict Type-Checking Options */
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "alwaysStrict": true,

    /* Additional Checks */
    "noUnusedLocals": true,
    
    /* Module Resolution Options */
    "moduleResolution": "node",
    "esModuleInterop": true,
    
    /* Experimental Options */
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,

    /* Advanced Options */
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

And I added some folders.
typeorm-sample(my project name)
L node_modules
L src
    L entity
    L migration
L package-lock.json
L package.json
L tsconfig.json
After that, I added a TypeORM config file.

ormconfig.json


{
    "type": "postgres",
    "host": "localhost",
    "port": 5432,
    "username": "test",
    "password": "test",
    "database": "test",
    "synchronize": true,
    "logging": true,
    "cache": false,
    "entities": [
       "src/entity/**/*.ts"
    ],
    "migrations": [
       "src/migration/**/*.ts"
    ],
    "subscribers": [
       "src/subscriber/**/*.ts"
    ],
    "cli": {
       "entitiesDir": "src/entity",
       "migrationsDir": "src/migration",
       "subscribersDir": "src/subscriber"
    }
 }

Though I created tables by ORM, I had to create empty database first. Or I would get exception by database was not found.

Add an Entity class

I added an Entity class to create table.

sample-user.ts


import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";

@Entity("SampleUser")
export class SampleUser {
    @PrimaryGeneratedColumn()
    id: number = -1;

    @Column()
    firstName: string = '';

    @Column()
    lastName: string = '';

    @Column()
    age: number = -1;
}

Table name

Because the table name was come from the entity class file name. So by default, when I created the table, it was named "sample_user". Because I wanted to name "SampleUser", I added the table name to @Entity().

Creating tables

When I accessed a database table, if it didn't exist, it would be created automatically. 
[2020-06-05 Update] When I connected the database, if it didn't exist, it would be created automatically.

index.ts


import "reflect-metadata";
import {createConnection} from "typeorm";
import { SampleUser } from "./entity/sample-user";

// The table would be created.
createConnection().then(async connection => {

    const user = new SampleUser();
    user.firstName = "Timber";
    user.lastName = "Saw";
    user.age = 25;
    
    await connection.manager.save(user);
    
    const users = await connection.manager.find(User);
    console.log("Loaded users: ", users);
    
}).catch(error => console.log(error));

After execution, the table would be created.

Primary key(auto increment)

I could use "@PrimaryGeneratedColumn()" to set auto increment ID. The datatype of database was "serial". An important thing was I couldn't set any custom values to auto increment values. In this sample, I couldn't change "id" value. When I added new "SampleUser", the "id" value what I set was ignored. When I tried updating, if I changed "id" value, it would be treated as new one.

NOT NULL

By default, the column data type was set as "NOT NULL". So if I wanted to set as nullable value, I had to add a propety into @Column().

sample-user.ts


@Entity("SampleUser")
export class SampleUser {
...
    @Column({ nullable: true })
    age: number = -1;
}

I could know other ColumnOptions here. typeorm/entities.md at master · typeorm/typeorm · GitHub And I could set column datatype through the ColumnOption. typeorm/entities.md at master · typeorm/typeorm · GitHub

Use transaction

How could I use transaction? There might be some ways to use it and I did like below.

index.ts


import "reflect-metadata";
import {createConnection } from "typeorm";
import { SampleUser } from "./entity/sample-user";

createConnection().then(async connection => {
    const queryRunner = connection.createQueryRunner();
    await queryRunner.startTransaction();
    try{
        const secondUser = new SampleUser();    
        secondUser.firstName = 'Hello2';
        secondUser.lastName = 'World2';
        secondUser.age = 36;
        await queryRunner.manager.save(secondUser);
        queryRunner.commitTransaction();
    }catch(error) {
        await queryRunner.rollbackTransaction();
    }
    finally {
        await queryRunner.release();
    }
}).catch(error => console.log(error));

One important thing was when I used transaction through QueryRunner, I couldn't use "connection.manager" to save data. The transaction only effected "queryRunner.manager". https://typeorm.io/#/transactions

コメント

このブログの人気の投稿

[Angular][ASP.NET Core] Upload chunked files

Intro I wanted to send files to Web application (made by ASP.NET Core). If the file size had been small, I didn't need do any special things. But when I tried to send a large file, the error was occurred by ASP.NET Core's limitation. Though I could change the settings, but I didn't want to do that, because I hadn't known the file sizes what would been actually using. So I splitted the data into chunks first, and sent them. After receiving all chunks, I merged them into one file. There might be some libraries or APIs (ex. Stream API) what did them automatically, but I couldn't find them. What I did [ASP.NET Core] Make CORS enabled [Angular] Split a large file into chunks [Angular][ASP.NET Core] Send and receive data as form data [ASP.NET Core] Merge chunks into one file [ASP.NET Core] Make CORS enabled Because the client side application(Angular) and the server side application(ASP.NET Core) had been separated, I had to make CORS(Cross-Origin Requests) ...

[Ubuntu] Install Docker, PostgreSQL(From DockerHub), PgAdmin4 + SELECT ALL

Intro I build development of PostgreSQL environment on Ubuntu this time. Because I haven't wanted to install PostgreSQL directly, I use Docker to install it. After installing them, I will try some SQL. Build development environments Docker According to the documents, I add repository and install "docker-ce", "docker-ce-cli", "containerd.io" Get Docker Engine - Community for Ubuntu | Docker Documentation When I had installed "Docker for Windows" on Windows, it had the GUI application. But maybe there is no GUI application for Ubuntu or I need installing another package? PostgreSQL(Docker Hub) Because I have wanted to use latest version, I just do "docker pull postgres". postgres - Docker Hub After getting PostgreSQL, I made mistake when I did "docker run". docker run (failed) docker run --name sample-shop -e POSTGRES_PASSWORD=postgres -d postgres -p 5432:5432 There are no any errors, but I can't access to...