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

[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) ...

[Nest.js] Show static files

Intro I wanted to use Nest.js and WebRTC(node-webrtc). NestJS - A progressive Node.js framework Documentation | NestJS - A progressive Node.js framework And because I wanted to try with simple page(not use JavaScript frameworks), I added static HTML, CSS, JavaScript into a Nest.js project. Prepare Install First, I installed @nestjs/cli. First steps | NestJS - A progressive Node.js framework As same as last time , I couldn't do global install because I had used Volta. But I could installed by volta. volta install @nestjs/cli Create project nest new nest-web-rtc-sample volta pin node@12 Run npm start After doing "npm start", I could getting "Hello World!" from http://localhost:3000. Add static files I could add static files by two ways. @nestjs/serve-static First one of them was using "serve-static". Serve Static | NestJS - A progressive Node.js framework npm install --save @nestjs/serve-static And I needed adding a module into app.modu...

[Angular] Sending file with Observable and showing loading screen

Intro When I tried sending file data on last time, I had confused with "promise.then", "async/await" and "Observable". [Angular][ASP.NET Core] Upload chunked files So I wanted to distinct them, and this time, I tried to use "Observable" because HttpClient return Observable<any>. Call observables in order I sended file in these steps. Read file by FileReader Create directory for saving chunks send and saving chunks merge chunks to one file and delete chunks Each steps used the former steps result. So I could write by Promise.then like below. this.executeStep1() // return Promise<UploadResult> .then(result => this.executeStep2(result)) // return Promise<UploadResult> .then(result => this.executeStep3(result)) // return Promise<UploadResult> .catch(reason => console.log(reason)); Result I could write with pipe & flatMap. file-uploader.service.ts public upload(file: File): Observable<U...