typeORM


typeORMの正式なドキュメントを読み、作成しました.
Create a model
データベースの開始は、テーブルの作成です.モデルを使用して作成できます.データベースにモデルを格納するには、データベース・テーブルが必要です.データベース・テーブルはモデルから作成する必要があります.(ただし、エンティティとして定義されているものに限られる)
Create an entity
Entityは@Entityデコレーションで飾られたモデルです.you work with entities everywhere with TypeORM. You can load/insert/update/remove and perform other operations with them.
Let's make our Photo model as an entity:
import { Entity } from "typeorm";

@Entity()
export class Photo {
    id: number;
    name: string;
    description: string;
    filename: string;
    views: number;
    isPublished: boolean;
}
Photo entityのDBテーブルを作成しました.ただし、tableにcolumnがないわけにはいかないので、columnを作成しましょう.
Adding table columns and a primary column
DBカラムを追加するには、@Columnデコーダを使用します.
また、エンティティごとに少なくとも1つのプライマリ・キー列が必要です.@PrimaryColumn装飾器を使用できます.
import { Entity, Column, PrimaryColumn } from "typeorm";

@Entity()
export class Photo {

    @PrimaryColumn() // PK
    id: number;

    @Column()
    name: string;

    @Column()
    description: string;

    @Column()
    filename: string;

    @Column()
    views: number;

    @Column()
    isPublished: boolean;
}
Creating an auto-generated column
Autogenerated columnは@PrimaryGeneratedColumn decoratorを使用します.
  @PrimaryGeneratedColumn()
    id: number;
Column data types
必要に応じて、カラムのデータ型と制限を指定できます.
かっこ内に対象として記入します.
import { Entity, Column, PrimaryGeneratedColumn } from "typeorm";

@Entity()
export class Photo {

    @PrimaryGeneratedColumn()
    id: number;

    @Column({ // data types limited
        length: 100
    })
    name: string;

    @Column("text")
    description: string;

    @Column()
    filename: string;

    @Column("double")
    views: number;

    @Column()
    isPublished: boolean;
}
Creating a connection to the database
Entityが作成されると、DBに接続する必要があります.
import "reflect-metadata";
import { createConnection } from "typeorm";
import { Photo } from "./entity/Photo";

createConnection({
    type: "mysql",
    host: "localhost",
    port: 3306,
    username: "root",
    password: "admin",
    database: "test",
    entities: [
        Photo
    ],
    synchronize: true,
    logging: false
}).then(connection => {
    // here you can start to work with your entities
}).catch(error => console.log(error));
Setting synchronize makes sure your entities will be synced with the database, every time you run the application.
appを実行するたびにDBを自動的に同期させます.
Creating and inserting a photo into the database
Now let's create a new photo to save it in the database:
import { createConnection } from "typeorm";
import { Photo } from "./entity/Photo";

createConnection(/*...*/).then(connection => { // createConnection 메서드를 이용해 DB와 연결 

    let photo = new Photo();
    photo.name = "Me and Bears";
    photo.description = "I am near polar bears";
    photo.filename = "photo-with-bears.jpg";
    photo.views = 1;
    photo.isPublished = true;

    return connection.manager
            .save(photo)
            .then(photo => {
                console.log("Photo has been saved. Photo id is", photo.id);
            });

}).catch(error => console.log(error));
Using Entity Manager
私たちはnew photoを作ってDBに保存したばかりです.EntityManagerを使用して保存できます.
import { createConnection } from "typeorm";
import { Photo } from "./entity/Photo";

createConnection(/*...*/).then(async connection => {

    /*...*/
    let savedPhotos = await connection.manager.find(Photo); // manager.method
    console.log("All photos from the db: ", savedPhotos);

}).catch(error => console.log(error));
Using Repositories
Now let's refactor our code and use Repository instead of EntityManager. Each entity has its own repository which handles all operations with its entity.
Repositories are more convenient to use than EntityManagers:
import { createConnection } from "typeorm";
import { Photo } from "./entity/Photo";

createConnection(/*...*/).then(async connection => {

    let photo = new Photo();
    photo.name = "Me and Bears";
    photo.description = "I am near polar bears";
    photo.filename = "photo-with-bears.jpg";
    photo.views = 1;
    photo.isPublished = true;

    let photoRepository = connection.getRepository(Photo); // getRepository

    await photoRepository.save(photo);
    console.log("Photo has been saved");

    let savedPhotos = await photoRepository.find();
    console.log("All photos from the db: ", savedPhotos);

}).catch(error => console.log(error));
save flow
  • createConnectionメソッドを使用してデータベース
  • に接続
  • Entity Managerを使用してデータベースに保存するか、Repositoriesを使用して
  • にデータベースに保存します.
    CRUD
    Updating in the database
    Now let's load a single photo from the database, update it and save it:
    import { createConnection } from "typeorm";
    import { Photo } from "./entity/Photo";
    
    createConnection(/*...*/).then(async connection => {
    
        /*...*/
        let photoToUpdate = await photoRepository.findOne(1);
        photoToUpdate.name = "Me, my friends and polar bears";
        await photoRepository.save(photoToUpdate);
    
    }).catch(error => console.log(error));
    しかし、.saveの方法で更新することもできる.
  • save - Saves a given entity or array of entities. If the entity already exist in the database, it is updated. If the entity does not exist in the database, it is inserted. It saves all given entities in a single transaction (in the case of entity, manager is not transactional). Also supports partial updating since all undefined properties are skipped. Returns the saved entity/entities.
  • したがって、上記のコードはこのように変更することができる.
    let photoToUpdate = await photoRepository.findOne(1);
    photoToUpdate.name = "Me, my friends and polar bears";
    await photoRepository.save(photoToUpdate);
    
    // .save 메서드 활용
    // photoRepository가 미리 DB에 저장되었다고 가정
    let photoToUpdate = await photoRepository.findOne(1); // photoRepository DB에서 findone을 한 후
    await photoRepository.save([ // find된 항목의 name값을 변경해 save
        photoToUpdate.name = "Me, my friends and polar bears"
    ]);
    Creating a one-to-one relation
    import { Entity, Column, PrimaryGeneratedColumn, OneToOne, JoinColumn } from "typeorm";
    import { Photo } from "./Photo";
    
    @Entity()
    export class PhotoMetadata {
    
        @PrimaryGeneratedColumn()
        id: number;
    
        @Column("int")
        height: number;
    
        @Column("int")
        width: number;
    
        @Column()
        orientation: string;
    
        @Column()
        compressed: boolean;
    
        @Column()
        comment: string;
    
        @OneToOne(type => Photo) // @OneToOne decorator
        @JoinColumn()
        photo: Photo;
    }
    @OneToOne decoratorを使用して、2つのエンティティ間で1対1の関係を確立できます.type => Photoは、関係を確立したいエンティティクラスを返す関数です.(直接classではありません)() => Photoと書くこともできますが、可読性のために上記と書きました.
    JoinColum
    また、@JoinColumn装飾器を使用することもできます.関係を表すレコーダを追加します.このレコーダには、関係の所有者が必要です.そのため、Photoはphoto metadataの天命になる.
    If you run the app, you'll see a newly generated table, and it will contain a column with a foreign key for the photo relation:
    +-------------+--------------+----------------------------+
    |                     photo_metadata                      |
    +-------------+--------------+----------------------------+
    | id          | int(11)      | PRIMARY KEY AUTO_INCREMENT |
    | height      | int(11)      |                            |
    | width       | int(11)      |                            |
    | comment     | varchar(255) |                            |
    | compressed  | boolean      |                            |
    | orientation | varchar(255) |                            |
    | photoId     | int(11)      | FOREIGN KEY                |
    +-------------+--------------+----------------------------+
    Save a one-to-one relation
    Now let's save a photo, its metadata and attach them to each other.
    import { createConnection } from "typeorm";
    import { Photo } from "./entity/Photo";
    import { PhotoMetadata } from "./entity/PhotoMetadata";
    
    createConnection(/*...*/).then(async connection => {
    
        // 1. create a photo
        let photo = new Photo();
        photo.name = "Me and Bears";
        photo.description = "I am near polar bears";
        photo.filename = "photo-with-bears.jpg";
        photo.views = 1;
        photo.isPublished = true;
    
        // 2. create a photo metadata
        let metadata = new PhotoMetadata();
        metadata.height = 640;
        metadata.width = 480;
        metadata.compressed = true;
        metadata.comment = "cybershoot";
        metadata.orientation = "portrait";
        metadata.photo = photo; // this way we connect them
    
        // 3. get entity repositories
        let photoRepository = connection.getRepository(Photo);
        let metadataRepository = connection.getRepository(PhotoMetadata);
    
        // 4. first we should save a photo
        await photoRepository.save(photo);
    
        // 5. photo is saved. Now we need to save a photo metadata
        await metadataRepository.save(metadata);
    
        // 6. done
        console.log("Metadata is saved, and the relation between metadata and photo is created in the database too");
    
    }).catch(error => console.log(error));
    metadataテーブルにはphotoが含まれているため、データベースに格納される順序は以下の通りです.
  • 写真とメタデータはDBに関連付けられ、
  • 写真データは、まずデータベースに保存され、
  • メタデータをDBに格納します.
  • メタデータに写真が含まれているため、サブエンティティを新規に格納する際に自動的に更新できません.