介绍
官网文档TypeORM把基本的操作都进行了描述。但是关于复杂条件的查询和事务相关的内容,不太适合实际的项目使用,所以编写这篇文章来说明这些内容。
这是Midwayjs系列的第四篇,其他三篇:
Midwayjs 之 配置mysql数据库并自动生成entity
Midwayjs 之 编写baseEntity和baseService以及思考
Midwayjs 之 编写baseController和配置swagger
查询操作
过滤
这里描述的查询条件,都是基于单表操作的。如果涉及多表操作,则可以直接编写SQL文件,或者根据官网QueryBuilder来进行扩展。
- 官网TypeORM提供了一个操作符枚举:
可以如下使用:
js
async queryAllByCode(codes: string[]) {
const where = {
ref_serve_code: In(codes),
};
return await super.list(where);
}
- 也可以这样使用:
js
async page(data: SystemQueryModel) {
const { name = '' } = data;
const where = {};
if (data.queryType === QueryType.MANAGER) {
where['manager_users'] = `Like(%,${data.operator_id},%)`;
} else if (data.queryType === QueryType.DEVELOPER) {
where['developer_users'] = `Like(%,${data.operator_id},%)`;
}
if (name) {
where['name'] = `Like(%${data.name}%)`;
}
return await super.pageBuilder(data, where);
}
直接SQL
js
async deleteDate(ids: string[]) {
return await this.tm
.db()
.query('DELETE FROM serve_controller_method WHERE id IN (?)', [ids]);
}
分页
分页查询的,一般都需要分装基类方法,直接上代码:
js
async pageBuilder(data, where = {}) {
const { _value } = data;
const newWhere: any = {};
Object.keys(where).forEach(element => {
if (where[element]) newWhere[element] = And(where[element]);
});
const [list, total] = await this.entity.findAndCount({
where: newWhere,
take: _value.pageSize,
skip: (_value.current - 1) * _value.pageSize,
});
return {
list,
pagination: { total, size: _value.pageSize, page: _value.current },
};
}
事务
进行事务操作时,需要使用TypeORMDataSourceManager对象,在transaction方法中进行操作。封装事务的基本如下:
js
import { Inject, Provide } from '@midwayjs/core';
import { EntityManager } from 'typeorm';
import { TypeORMDataSourceManager } from '@midwayjs/typeorm';
import { Context } from '@midwayjs/koa';
@Provide()
export class TransactionManager {
@Inject()
dataSourceManager: TypeORMDataSourceManager;
@Inject()
ctx: Context;
async inTx(func) {
const dataSource = this.dataSourceManager.getDataSource('default');
return await dataSource.transaction(async transactionalEntityManager => {
this.ctx.entityManager = transactionalEntityManager;
await func();
});
}
db(): EntityManager {
if (this.ctx.entityManager) {
return this.ctx.entityManager;
}
const dataSource = this.dataSourceManager.getDataSource('default');
return dataSource.manager;
}
}
使用样例
多个删除、修改、新增操作,样例代码如下:
js
@Provide()
export class ServeService extends BaseService<ServeRegister> {
@Inject() // 必须在这里引入事务基类
tm: TransactionManager;
async deleteDate(ids: string[]) {
// 包住 复杂操作
return await this.tm.inTx(async () => {
// 查询所有服务
const allServe = await this.queryAll(ids);
const allServeCode: string[] = [];
// TODO 获取数据操作
const allControllerId: string[] = [];
// TODO 获取数据操作
const allMethodId: string[] = [];
// TODO 获取数据操作
// 删除所有服务、控制器、方法
if (allMethodId.length > 0)
await this.methodService.deleteDate(allMethodId);
if (allControllerId.length > 0)
await this.serveController.deleteDate(allControllerId);
return await this.tm.db().delete(ServeRegister, ids);
});
}
}
具体操作的服务,样例代码如下:
js
@Provide()
export class ServeControllerMethodService extends BaseService<ServeControllerMethod> {
@Inject() // 必须在这里引入事务基类
tm: TransactionManager;
async deleteDate(ids: string[]) {
return await this.tm.db().delete(ServeControllerMethod, ids);
}
}
通过上述的操作,事务回滚起效了,如果出现异常的话。
注意
- 这种多个异步操作,必须添加 await 标识符。不然其他异常操作里面出现异常,不会被上层捕获,导致事务无法回滚。
- 上述都是单数据库操作的配置操作,如果是多数据库操作的话,则需要做相关的调整。具体参考官网多数据库支持。