import { Config, Provide } from '@midwayjs/core'; import { InjectDataSource, InjectEntityModel } from '@midwayjs/typeorm'; import { DataSource, Repository, getCustomRepository, getManager } from 'typeorm'; import { get, head, upperFirst } from 'lodash'; import * as fs from 'fs'; import * as path from 'path'; @Provide() export class DbBackupService { @InjectDataSource('default') defaultDataSource: DataSource; @Config('PathConfig.path') filePath; dbBackupDir = 'dbBackUp'; async getTables() { console.log('to dump'); const entitys = this.defaultDataSource.entityMetadatas; const dbBackUpPath = path.resolve(this.filePath, this.dbBackupDir); const res = fs.existsSync(dbBackUpPath); if (!res) { fs.mkdirSync(dbBackUpPath); } for (const e of entitys) { const tableNames = e.givenTableName; const dataSql = `SELECT * from "public"."${tableNames}" ORDER BY "id" ;`; const dataRes = await this.defaultDataSource.query(dataSql); const fileFullPath = path.resolve(dbBackUpPath, `${tableNames}.json`); fs.writeFileSync(fileFullPath, JSON.stringify(dataRes), 'utf-8'); } console.log('dump finish'); } /** * 根据表名,找entity * 有entity,通过数据源创建createQueryBuilder.对数据进行批量添加 * @param {string} dirPath 文件夹路径,没有就默认使用备份路径 */ async restore(dirPath?: string) { console.log('to restore'); if (!dirPath) dirPath = path.resolve(this.filePath, this.dbBackupDir); const dbBackUpPathDir = dirPath; let dir = fs.readdirSync(dbBackUpPathDir); dir = dir.map(i => { const arr = i.split('.'); return head(arr); }); for (const tableName of dir) { // 清空表, 重置id; console.log(tableName); const filePath = path.resolve(dbBackUpPathDir, `${tableName}.json`); let datas = fs.readFileSync(filePath, 'utf-8'); if (datas) datas = JSON.parse(datas); console.log(`${tableName} start`); await this.defaultDataSource.query(`TRUNCATE TABLE "public"."${tableName}" RESTART IDENTITY RESTRICT;`); await this.defaultDataSource.query(`SELECT setval('"${tableName}_id_seq"', (SELECT max(id) FROM "${tableName}"));`); const entities: any = this.defaultDataSource.options.entities; const entity = entities.find(f => get(f, 'name') === `${upperFirst(tableName)}`); for (const i of datas) { try { // 需要处理id的问题 const data_id = get(i, 'id', 1); // 获取当前表id的序列 const lastIdResult = await this.defaultDataSource.query(`SELECT max(id) FROM "${tableName}"`); let last_id = get(head(lastIdResult), 'max', 0); // 判断same_id: 表中最后一个id和当前数据id是否一致 let same_id = last_id === data_id; if (!same_id && data_id > 1) { // 不一致:只有一种情况----当前数据的id比表中的数据id要大.那就直接执行id补上 await this.defaultDataSource.query(`SELECT setval('"${tableName}_id_seq"', ${data_id - 1});`); } const builder = await this.defaultDataSource.manager.createQueryBuilder().insert().into(entity); await builder.values(i).execute(); } catch (error) { console.log(`${tableName} - ${get(i, 'id')} - 发生错误`); console.log(error); } } } console.log('restore finish'); } }