认识TypeORM
TypeORM 是一个ORM (opens new window)框架,它可以运行在 NodeJS、Browser、Cordova、PhoneGap、Ionic、React Native、Expo 和 Electron 平台上,可以与 TypeScript 和 JavaScript (ES5,ES6,ES7,ES8)一起使用。 它的目标是始终支持最新的 JavaScript 特性并提供额外的特性以帮助你开发任何使用数据库的(不管是只有几张表的小型应用还是拥有多数据库的大型企业应用)应用程序。
不同于现有的所有其他 JavaScript ORM 框架,TypeORM 支持 Active Record和 Data Mapper 模式,这意味着你
可以以最高效的方式编写高质量的、松耦合的、可扩展的、可维护的应用程序。
TypeORM的特性
支持 DataMapper 和 ActiveRecord (随你选择)
实体和列
数据库特性列类型
实体管理
存储库和自定义存储库
清晰的对象关系模型
关联(关系)
贪婪和延迟关系
单向的,双向的和自引用的关系
支持多重继承模式
级联
索引
事务
迁移和自动迁移
连接池
主从复制
使用多个数据库类型
跨数据库和跨模式查询
优雅的语法,灵活而强大的 QueryBuilder
左联接和内联接
使用联查查询的适当分页
查询缓存
原始结果流
日志
监听者和订阅者(钩子)
支持闭包表模式
在模型或者分离的配置文件中声明模式
json / xml / yml / env 格式的连接配置
支持 MySQL / MariaDB / Postgres / SQLite / Microsoft SQL Server / Oracle / sql.js
支持 MongoDB NoSQL 数据库
可在 NodeJS / 浏览器 / Ionic / Cordova / React Native / Expo / Electron 平台上使用
支持 TypeScript 和 JavaScript
生成高性能、灵活、清晰和可维护的代码
遵循所有可能的最佳实践
命令行工具
安装
通过npm安装:
npm install typeorm --save
你还需要安装 reflect-metadata:
npm install reflect-metadata --save
并且需要在应用程序的全局位置导入(例如在app.ts中)
import “reflect-metadata”;
你可能还需要安装 node typings(以此来使用 Node 的智能提示):
npm install @types/node –save
安装数据库驱动 MySQL
npm install mysql --save (也可以安装 mysql2)
此外,请确保你使用的是 TypeScript 编译器版本2.3或更高版本,并且已经在tsconfig.json中启用了以下设置:
“emitDecoratorMetadata”: true,
“experimentalDecorators”: true,
你可能还需要在编译器选项的lib中启用es6, ,或者从@types安装es6-shim
开始使用 TypeORM 的最快方法是使用其 CLI 命令生成启动项目。 只有在 NodeJS 应用程序中使用
TypeORM 时,此操作才有效。
首先全局安装 TypeORM:
npm install typeorm –g
然后转到要创建新项目的目录并运行命令:
typeorm init --name MyProject --database mysql
其中name是项目的名称,database是您将使用的数据库。
数据库可以是以下值之一: mysql, mariadb, postgres, sqlite, mssql, oracle, mongodb, cordova, react-native, expo, nativescript.
你还可以在现有 node 项目上运行typeorm init,但要注意,此操作可能会覆盖已有的某些文件。
数据库配置文件
大多数情况下,我们希望将连接选项存储在单独的配置文件中,因为此方式使管理变得更方便和容易。 TypeORM 支持多个配置源。你只需要在应用程序的根目录(package.json附近)中创建一个ormconfig.[format]文件存放连接配置,并在应用程序中调用createConnection(),而不传递任何参数配置
支持的 ormconfig 文件格式有:.json, .js, .env, .yml 和 .xml
import { createConnection } from "typeorm";
// createConnection方法会自动读取来自ormconfig文件或环境变量中的连接选项
createconnection = await createConnection();
使用ormconfig.json
在项目根目录(package.json附近)中创建ormconfig.json,并包含以下内容:
{
"type": "mysql",
"host": "localhost",
"port": 3306,
"username": "test",
"password": "test",
"database": "test"
}
如果要创建多个连接,则只需在数组中添加多个连接:
[
{
"name": "default",
"type": "mysql",
...
},
{
"name": "second-connection",
"type": "mysql",
....
}
]
使用ormconfig.js
在项目根目录(package.json附近)中创建ormconfig.js,并包含以下内容
module.exports = {
type: "mysql",
host: "localhost",
port: 3306,
username: "test",
password: "test",
database: "test"
};
如果要创建多个连接,则只需在数组中添加多个连接
使用环境变量
在项目根目录(package.json附近)中创建.env 或者 ormconfig.env,并包含以下内容:
TYPEORM_CONNECTION = mysql
TYPEORM_HOST = localhost
TYPEORM_USERNAME = root
TYPEORM_PASSWORD = admin
TYPEORM_DATABASE = test
TYPEORM_PORT = 3000
TYPEORM_SYNCHRONIZE = true
TYPEORM_LOGGING = true
TYPEORM_ENTITIES = entity/.*js,modules/**/entity/.*js
ormconfig.env只能在开发期间使用。
无法使用env文件或环境变量定义多个连接
使用ormconfig.yml
在项目根目录(package.json附近)中创建ormconfig.yml,并包含以下内容:
default: # 默认连接
host: "localhost"
port: 3306
username: "test"
password: "test"
database: "test"
second-connection: # 其他连接
host: "localhost"
port: 3306
username: "test"
password: "test"
database: "test2"
你可以使用任一连接。
使用ormconfig.xml
在项目根目录(package.json附近)中创建ormconfig.xml,并包含以下内容:
localhost
root
admin
test
3000
true
localhost
root
admin
test2
3000
true
你可以使用任一连接。
Typeorm使用哪个配置文件
连接选项是你传递给createConnection或在ormconfig文件中定义的连接配置。不同的数据库有自己的特定连接选项。
常用的连接选项:
type - 数据库类型。你必须指定要使用的数据库引擎。该值可以是"mysql…"。此选项是必需的。
name - 连接名。 在使用 getConnection(name: string) 或 ConnectionManager.get(name: string)时候需要用到。不同连接的连接名称不能相同,它们都必须是唯一的。如果没有给出连接名称,那么它将被设置为"default"。
entities - 要加载并用于此连接的实体。接受要加载的实体类和目录路径。目录支持 glob 模式。示例:
entities: [Post, Category, “entity/.js", "modules/**/entity/.js”]。
subscribers - 要加载并用于此连接的订阅者。接受要加载的实体类和目录。
migrations - 要加载和用于此连接的迁移。接受要加载的迁移类和目录
logging - 指示是否启用日志记录。如果设置为true,则将启用查询和错误日志记录。你还可以指定要启用的不同类型的日志记录,例如[“query”, “error”, “schema”]
有时你可能希望使用不同格式的多个配置。 当调用getConnectionOptions()或尝试在没有连接选项的情况下使用
createConnection()时,Typeorm将尝试按以下顺序加载配置:
从另一个ormconfig.[format]文件,按此顺序:[js,ts,json,yml,yaml,xml]。
注意,Typeorm将使用找到的第一个有效方法,而不会加载其他方法。 例如,如果在环境中找到配置,Typeorm将不会加载ormconfig.[format]文件。
ConnectionOptions
maxQueryExecutionTime - 如果查询执行时间超过此给定的最大执行时间(以毫秒为单位),则 logger 将记录此查询。
entityPrefix - 给此数据库连接上的所有表(或集合)加的前缀。
dropSchema - 每次建立连接时删除架构。请注意此选项,不要在生产环境中使用它,否则将丢失所有生产数据。但是此选项在调试和开发期间非常有用。
synchronize - 指示是否在每次应用程序启动时自动创建数据库架构。 请注意此选项,不要在生产环境中使用它,否则将丢失所有生产数据。但是此选项在调试和开发期间非常有用。
cache - 启用实体结果缓存。
cli.entitiesDir - CLI 默认情况下创建实体的目录。
cli.migrationsDir - CLI 默认情况下创建迁移的目录。
cli.subscribersDir - CLI 默认情况下创建订阅者的目录。
不同数据库,配置可能不同,请查看 Connection 选项 | TypeORM 中文文档 (biunav.com)
连接Connection
从ormconfig文件加载所有连接选项
import {createConnections} from "typeorm";
const connections = await createConnections();
指定要按名称创建的连接
import {createConnection} from "typeorm";
const connection = await createConnection("db2Connection");
使用连接时,必须指定连接名称以获取特定连接:
import {getConnection} from "typeorm";
const db1Connection = getConnection("db1Connection");
// 现在可以使用"db1"数据库...
const db2Connection = getConnection("db2Connection");
// 现在可以使用"db2"数据库...
使用EntityManager
Repository就像EntityManager一样,但其操作仅限于具体实体。
import "reflect-metadata";
import {createConnection,getManager} from "typeorm";
import {User} from "./entity/User";
createConnection().then(async ()=>{
console.log('数据库连接成功')
// 获取实体管理器
const entityManager = getManager() // 你也可以通过 getConnection().manager 获取
let user:User = new User('张','三',18)
// 添加
user = await entityManager.save(user)
// 查询所有
const userList:User[] = await entityManager.find(User)
let newUser:User = new User('张','三',18,user.id)
// 修改
await entityManager.save(newUser)
// 根据id查询
newUser = await entityManager.findOne(User,newUser.id)
// 删除
await entityManager.delete(User,newUser.id)
await [allPhotos, photosCount] = entityManager.findAndCount()
}).catch((error:Error)=> console.log(error))
使用Repository
Repository就像EntityManager一样,但是其操作仅限于具体实现。
import "reflect-metadata";
import {createConnection, getRepository} from "typeorm";
import {User} from "./entity/User";
createConnection().then(async () => {
const userRepository = getRepository(User);
}).catch((error:Error) => console.log(error))
自定义存储库
可以创建一个自定义存储库,其中应包含使用数据库的方法。通常为单个实体创建自定义存储库,并包含其特定的查询。
import { EntityRepository, Repository } from "typeorm";
import { User } from "../entity/User";
@EntityRepository(User)
export class UserRepository extends Repository {
findByName(firstName: string, lastName: string) {
return this.findOne({ firstName, lastName });
}
}
import { getCustomRepository } from "typeorm";
import { UserRepository } from "./repository/UserRepository";
// 或connection.getCustomRepository或manager.getCustomRepository()
const userRepository = getCustomRepository(UserRepository);
const user = userRepository.create(); // 和 const user = new User();一样
user.firstName = "Timber";
user.lastName = "Saw";
await userRepository.save(user);
const timber = await userRepository.findByName("Timber", "Saw");
如你所见,你也可以使用getCustomRepository获取repository,并且可以访问在其中创建的任何方法以及标准实体repository中的任何方法。