Midwayjs 之 编写typeorm的事务配置和查询过滤

介绍

官网文档TypeORM把基本的操作都进行了描述。但是关于复杂条件的查询和事务相关的内容,不太适合实际的项目使用,所以编写这篇文章来说明这些内容。

这是Midwayjs系列的第四篇,其他三篇:
Midwayjs 之 配置mysql数据库并自动生成entity
Midwayjs 之 编写baseEntity和baseService以及思考
Midwayjs 之 编写baseController和配置swagger

查询操作

过滤

这里描述的查询条件,都是基于单表操作的。如果涉及多表操作,则可以直接编写SQL文件,或者根据官网QueryBuilder来进行扩展。

  1. 官网TypeORM提供了一个操作符枚举:

可以如下使用:

js 复制代码
  async queryAllByCode(codes: string[]) {
    const where = {
      ref_serve_code: In(codes),
    };
    return await super.list(where);
  }
  1. 也可以这样使用:
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);
  }
}

通过上述的操作,事务回滚起效了,如果出现异常的话。

注意

  1. 这种多个异步操作,必须添加 await 标识符。不然其他异常操作里面出现异常,不会被上层捕获,导致事务无法回滚。
  2. 上述都是单数据库操作的配置操作,如果是多数据库操作的话,则需要做相关的调整。具体参考官网多数据库支持
相关推荐
罗政3 小时前
[附源码]超简洁个人博客网站搭建+SpringBoot+Vue前后端分离
vue.js·spring boot·后端
拾光师4 小时前
spring获取当前request
java·后端·spring
Java小白笔记6 小时前
关于使用Mybatis-Plus 自动填充功能失效问题
spring boot·后端·mybatis
JOJO___7 小时前
Spring IoC 配置类 总结
java·后端·spring·java-ee
一个很帅的帅哥7 小时前
实现浏览器的下拉加载功能(类似知乎)
开发语言·javascript·mysql·mongodb·node.js·vue·express
白总Server8 小时前
MySQL在大数据场景应用
大数据·开发语言·数据库·后端·mysql·golang·php
Lingbug9 小时前
.Net日志组件之NLog的使用和配置
后端·c#·.net·.netcore
计算机学姐9 小时前
基于SpringBoot+Vue的篮球馆会员信息管理系统
java·vue.js·spring boot·后端·mysql·spring·mybatis
好兄弟给我起把狙10 小时前
[Golang] Select
开发语言·后端·golang
程序员大金10 小时前
基于SpringBoot+Vue+MySQL的智能物流管理系统
java·javascript·vue.js·spring boot·后端·mysql·mybatis