TypeORM 日常使用

date
Mar 13, 2020
slug
klyjrhbu
status
Published
tags
Node
summary
type
Post
 
本篇记录日常中常见的问题,主要是 CRUD。两个版本 API,内容大部分一样:

[TOC]

常用 API

hasId - 检查是否定义了给定实体的主列属性。 getId - 获取给定实体的主列属性值。复合主键返回的值将是一个具有主列名称和值的对象。 save - 保存给定实体或实体数组。不存在则插入,存在则更新,支持部分属性更新。Active Record 模式下是事务的,在 Data Mapper 模式下不是事务的。
await repository.save(user);
await repository.save([category1, category2, category3]);
remove - 删除给定的实体或实体数组。
await repository.save(user);
await repository.save([category1, category2, category3]);
insert - 插入新实体或实体数组。
await repository.insert({
  firstName: "Timber",
  lastName: "Timber"
});

await manager.insert(User, [
  {
    firstName: "Foo",
    lastName: "Bar"
  },
  {
    firstName: "Rizz",
    lastName: "Rak"
  }
]);
update - 通过给定的更新选项或实体 ID 部分更新实体。
await repository.update({ firstName: "Timber" }, { firstName: "Rizzrak" });
// 执行 UPDATE user SET firstName = Rizzrak WHERE firstName = Timber

await repository.update(1, { firstName: "Rizzrak" });
// 执行 UPDATE user SET firstName = Rizzrak WHERE id = 1
delete -根据实体 id, ids 或给定的条件删除实体:
await repository.delete(1);
await repository.delete([1, 2, 3]);
await repository.delete({ firstName: "Timber" });
count - 符合指定条件的实体数量。对分页很有用。
const count = await repository.count({ firstName: "Timber" });
find - 查找指定条件的实体,详细 option
const count = await repository.count({ firstName: "Timber" });

userRepository.find({
    select: ["firstName", "lastName"],
    relations: ["profile", "photos", "videos"],
    where: {
        firstName: "Timber",
        lastName: "Saw"
    },
    order: {
        name: "ASC",
        id: "DESC"
    },
    skip: 5,
    take: 10,
    cache: true
});
findAndCount - 查找指定条件的实体。还会计算与给定条件匹配的所有实体数量, 但是忽略分页设置 (skip 和 take 选项)。
const [timbers, timbersCount] = await repository.findAndCount({ firstName: "Timber" });
findByIds - 按 ID 查找多个实体。
const users = await repository.findByIds([1, 2, 3]);
findOne - 查找匹配某些 ID 或查找选项的第一个实体。
const user = await repository.findOne(1);
const timber = await repository.findOne({ firstName: "Timber" });
findOneOrFail - 查找匹配某些 ID 或查找选项的第一个实体。 如果没有匹配,则 Rejects 一个 promise。
const user = await repository.findOneOrFail(1);
const timber = await repository.findOneOrFail({ firstName: "Timber" });
query - 执行原始 SQL 查询。
const rawData = await repository.query(`SELECT * FROM USERS`);
clear - 清除给定表中的所有数据(truncates/drops)。
await repository.clear();

其他选项

SaveOptions选项可以传递 save, insert 和 update 参数。
  • save:在事务里执行到 save,会向数据库插一条数据,如果事务里异常,会回滚,删除数据库中插入的数据。
  • persist:在事务里执行到 persist,不会向数据库插数据,事务 commit 了才会插入数据。
RemoveOptions可以传递 remove 和 delete 参数。

缓存查询

QueryBuilder 和 Repository 查询后的结果都可以缓存,需在ormconfig.json中启用cache: true首次启用缓存时,必须同步数据库架构(使用 CLI,migrations 或 synchronize 连接选项)。
// 全局配置
{
    type: "mysql",
    host: "localhost",
    username: "test",
    ...
    cache: {    // 或 cache: true
        duration: 30000 // 30秒
    }
}
// 默认缓存生存期为1000 ms
const users = await connection
  .createQueryBuilder(User, "user")
  .where("user.isAdmin = :isAdmin", { isAdmin: true })
  .cache(true)  // cache(60000) - 1分钟
  .getMany();

// 等效于

const users = await connection.getRepository(User).find({
  where: { isAdmin: true },
  cache: true   // cache(60000) - 1分钟
});
默认情况下,使用一个名为 query-result-cache 的单独表,并在那里存储所有查询和结果,表名是可配置的。也可以通过设置“cache id”精确控制缓存。
const users = await connection
  .createQueryBuilder(User, "user")
  .where("user.isAdmin = :isAdmin", { isAdmin: true })
  .cache("users_admins", 25000)
  .getMany();

const users = await connection.getRepository(User).find({
  where: { isAdmin: true },
  cache: {
    id: "users_admins",
    milisseconds: 25000
  }
});

// 手动清除缓存
await connection.queryResultCache.remove(["users_admins"]);
ormconfig.jsoncache里,也可将缓存类型更改为“redis”或者“ioredis”,options 参考node_redis specific optionsioredis specific options

© 刘德华 2020 - 2023