typeorm

523 阅读3分钟

typeorm是一个ORM框架,它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了。

数据库连接

1.使用createConnection或者createConnections进行数据库连接

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 => {
   // 这里可以写实体操作相关的代码
 })
 .catch(error => console.log(error)); 
  • entities属性是配置需要在数据库中映射出表的实体类。也可以使用通配符进行实体的配置:
    entities: [__dirname + "/entity/*.js"],
  • 设置synchronize可确保每次运行应用程序时实体都将与数据库同步。
  • 使用createConnections可以创建多个数据库连接

2,使用配置ormconfig.json文件的方式进行数据库连接, 当使用配置文件的时候,createConnection或者createConnections调用传入为空的时候,会自动查找配置文件的内容,然后根据此配置进行数据库的连接。

{\
"type": "mysql",\
"host": "localhost",\
"port": 3306,\
"username": "test",\
"password": "test",\
"database": "test"\
}

typeorm也支持其他ormconfig.[format]格式的文件的配置文件。支持的 ormconfig 文件格式有:.json.js.env.yml 和 .xml

3,使用ConnectionManager进行数据库连接

import { getConnectionManager, ConnectionManager, Connection } from "typeorm";
const connectionManager = getConnectionManager();
const connection = connectionManager.create({
  type: "mysql",
  host: "localhost",
  port: 3306,
  username: "test",
  password: "test",
  database: "test"
});
await connection.connect(); // 执行连接

如果你想创建连接并获取实例可以使用此种方式。但是这种方式将不能使用getConnection获取连接。

获取数据库连接:

import { getConnection } from "typeorm";
const secondConnection = getConnection("test2-connection");

可以在一个连接中使用多个数据库,只需要在对应的实体类中加上对应的数据库即可:

@Entity({ database: "secondDB" })
export class User {}

实体-数据库表的映射

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";
@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  firstName: string;

  @Column()
  lastName: string;

  @Column("double")
  age: number;
}
  • @Entity注解能够实现实体表到数据库表的映射,
  • @Column是对应列的映射,可以设置对应列的类型。

创建不同关系的数据库表

1.一对一关系

@Entity()
export class PhotoMetadata {
...
@OneToOne(type => Photo)
@JoinColumn()
photo: Photo;
}
  • @OneToOne表示与哪个实体对应的数据库表进行关联关系
  • @JoinColumn()表示对应关系的所有者 此实体对应的数据库表photo-metadata中会有自动建立一个外键:
photoId | int(11) | FOREIGN KEY

现在PhotoMetadata和Photo之间建立的只是单向关系,Photos对PhotoMetadata的信息却一无所知,为了解决这个问题需要建立双向关系:

@Entity()
export class PhotoMetadata {
  @OneToOne(type => Photo, photo => photo.metadata)
  @JoinColumn()
  photo: Photo;
}

@Entity()
export class Photo {
  @OneToOne(type => PhotoMetadata, photoMetadata => photoMetadata.photo)
  metadata: PhotoMetadata;
}

取出关系对象的数据:

 let photoRepository = connection.getRepository(Photo);
 let photos = await photoRepository.find({ relations: ["metadata"] });

可以看出通过photoRepository可以拿到phone实体关联的PhotoMetadata数据

2.一对多关系

@Entity()
export class Author {
  @OneToMany(type => Photo, photo => photo.author) 
  photos: Photo[];
}


@Entity()
export class Photo {
  @ManyToOne(type => Author, author => author.photos)
  author: Author;
}

此关系在数据库创建表: Author不会对关系做任何字段的保存,一对多的关系字段总是保存在多的一方,所以会保存在photo表中:

authorId | int(11) | FOREIGN KEY

3.多对多关系

@Entity()
export class Album {
  @ManyToMany(type => Photo, photo => photo.albums)
  @JoinTable()
  photos: Photo[];
}

export class Photo {
  @ManyToMany(type => Album, album => album.photos)
  albums: Album[];
}

@JoinTable指定关系所有者
运行后,ORM 将创建album_photos_photo_albums_联结表:

 album_id | int(11) | PRIMARY KEY FOREIGN KEY 
 photo_id | int(11) | PRIMARY KEY FOREIGN KEY

操作数据库的三种方式

1.Entity Manager

createConnection(/*...*/)
  .then(async connection => {
    /*...*/
    let savedPhotos = await connection.manager.find(Photo);
    console.log("All photos from the db: ", savedPhotos);
  })
  .catch(error => console.log(error));

2.Repositories

createConnection(/*...*/)
  .then(async connection => {
     ...省略部分代码
    let photoRepository = connection.getRepository(Photo);
    await photoRepository.save(photo);
  })

3.QueryBuilder(构建几乎任何复杂性的 SQL 查询)

createConnection(/*...*/)
  .then(async connection => {
    let photos = await connection
      .getRepository(Photo)
      .createQueryBuilder("photo")
      .innerJoinAndSelect("photo.metadata", "metadata")
      .getMany();
  })
  .catch(error => console.log(error));