333
schangxiang@126.com
2025-09-19 18966e02fb573c7e2bb0c6426ed792b38b910940
1
{"version":3,"sources":["../browser/src/persistence/EntityPersistExecutor.ts"],"names":[],"mappings":"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","file":"EntityPersistExecutor.js","sourcesContent":["import {ObjectLiteral} from \"../common/ObjectLiteral\";\nimport {SaveOptions} from \"../repository/SaveOptions\";\nimport {RemoveOptions} from \"../repository/RemoveOptions\";\nimport {MustBeEntityError} from \"../error/MustBeEntityError\";\nimport {SubjectExecutor} from \"./SubjectExecutor\";\nimport {CannotDetermineEntityError} from \"../error/CannotDetermineEntityError\";\nimport {QueryRunner} from \"../query-runner/QueryRunner\";\nimport {Connection} from \"../connection/Connection\";\nimport {Subject} from \"./Subject\";\nimport {OneToManySubjectBuilder} from \"./subject-builder/OneToManySubjectBuilder\";\nimport {OneToOneInverseSideSubjectBuilder} from \"./subject-builder/OneToOneInverseSideSubjectBuilder\";\nimport {ManyToManySubjectBuilder} from \"./subject-builder/ManyToManySubjectBuilder\";\nimport {SubjectDatabaseEntityLoader} from \"./SubjectDatabaseEntityLoader\";\nimport {CascadesSubjectBuilder} from \"./subject-builder/CascadesSubjectBuilder\";\nimport {OrmUtils} from \"../util/OrmUtils\";\nimport {PromiseUtils} from \"../util/PromiseUtils\";\n\n/**\n * Persists a single entity or multiple entities - saves or removes them.\n */\nexport class EntityPersistExecutor {\n\n    // -------------------------------------------------------------------------\n    // Constructor\n    // -------------------------------------------------------------------------\n\n    constructor(protected connection: Connection,\n                protected queryRunner: QueryRunner|undefined,\n                protected mode: \"save\"|\"remove\",\n                protected target: Function|string|undefined,\n                protected entity: ObjectLiteral|ObjectLiteral[],\n                protected options?: SaveOptions & RemoveOptions) {\n    }\n\n    // -------------------------------------------------------------------------\n    // Public Methods\n    // -------------------------------------------------------------------------\n\n    /**\n     * Executes persistence operation ob given entity or entities.\n     */\n    execute(): Promise<void> {\n\n        // check if entity we are going to save is valid and is an object\n        if (!this.entity || !(this.entity instanceof Object))\n            return Promise.reject(new MustBeEntityError(this.mode, this.entity));\n\n        // we MUST call \"fake\" resolve here to make sure all properties of lazily loaded relations are resolved\n        return Promise.resolve().then(async () => {\n\n            // if query runner is already defined in this class, it means this entity manager was already created for a single connection\n            // if its not defined we create a new query runner - single connection where we'll execute all our operations\n            const queryRunner = this.queryRunner || this.connection.createQueryRunner(\"master\");\n\n            // save data in the query runner - this is useful functionality to share data from outside of the world\n            // with third classes - like subscribers and listener methods\n            if (this.options && this.options.data)\n                queryRunner.data = this.options.data;\n\n            try {\n\n                // collect all operate subjects\n                const entities: ObjectLiteral[] = this.entity instanceof Array ? this.entity : [this.entity];\n                const entitiesInChunks = this.options && this.options.chunk && this.options.chunk > 0 ? OrmUtils.chunk(entities, this.options.chunk) : [entities];\n\n                // console.time(\"building subject executors...\");\n                const executors = await Promise.all(entitiesInChunks.map(async entities => {\n                    const subjects: Subject[] = [];\n\n                    // create subjects for all entities we received for the persistence\n                    entities.forEach(entity => {\n                        const entityTarget = this.target ? this.target : entity.constructor;\n                        if (entityTarget === Object)\n                            throw new CannotDetermineEntityError(this.mode);\n\n                        subjects.push(new Subject({\n                            metadata: this.connection.getMetadata(entityTarget),\n                            entity: entity,\n                            canBeInserted: this.mode === \"save\",\n                            canBeUpdated: this.mode === \"save\",\n                            mustBeRemoved: this.mode === \"remove\"\n                        }));\n                    });\n\n                    // console.time(\"building cascades...\");\n                    // go through each entity with metadata and create subjects and subjects by cascades for them\n                    const cascadesSubjectBuilder = new CascadesSubjectBuilder(subjects);\n                    subjects.forEach(subject => {\n                        // next step we build list of subjects we will operate with\n                        // these subjects are subjects that we need to insert or update alongside with main persisted entity\n                        cascadesSubjectBuilder.build(subject);\n                    });\n                    // console.timeEnd(\"building cascades...\");\n\n                    // load database entities for all subjects we have\n                    // next step is to load database entities for all operate subjects\n                    // console.time(\"loading...\");\n                    await new SubjectDatabaseEntityLoader(queryRunner, subjects).load(this.mode);\n                    // console.timeEnd(\"loading...\");\n\n                    // console.time(\"other subjects...\");\n                    // build all related subjects and change maps\n                    if (this.mode === \"save\") {\n                        new OneToManySubjectBuilder(subjects).build();\n                        new OneToOneInverseSideSubjectBuilder(subjects).build();\n                        new ManyToManySubjectBuilder(subjects).build();\n                    } else {\n                        subjects.forEach(subject => {\n                            if (subject.mustBeRemoved) {\n                                new ManyToManySubjectBuilder(subjects).buildForAllRemoval(subject);\n                            }\n                        });\n                    }\n                    // console.timeEnd(\"other subjects...\");\n                    // console.timeEnd(\"building subjects...\");\n                    // console.log(\"subjects\", subjects);\n\n                    // create a subject executor\n                    return new SubjectExecutor(queryRunner, subjects, this.options);\n                }));\n                // console.timeEnd(\"building subject executors...\");\n\n                // make sure we have at least one executable operation before we create a transaction and proceed\n                // if we don't have operations it means we don't really need to update or remove something\n                const executorsWithExecutableOperations = executors.filter(executor => executor.hasExecutableOperations);\n                if (executorsWithExecutableOperations.length === 0)\n                    return;\n\n                // start execute queries in a transaction\n                // if transaction is already opened in this query runner then we don't touch it\n                // if its not opened yet then we open it here, and once we finish - we close it\n                let isTransactionStartedByUs = false;\n                try {\n\n                    // open transaction if its not opened yet\n                    if (!queryRunner.isTransactionActive) {\n                        if (!this.options || this.options.transaction !== false) { // start transaction until it was not explicitly disabled\n                            isTransactionStartedByUs = true;\n                            await queryRunner.startTransaction();\n                        }\n                    }\n\n                    // execute all persistence operations for all entities we have\n                    // console.time(\"executing subject executors...\");\n                    await PromiseUtils.runInSequence(executorsWithExecutableOperations, executor => executor.execute());\n                    // console.timeEnd(\"executing subject executors...\");\n\n                    // commit transaction if it was started by us\n                    // console.time(\"commit\");\n                    if (isTransactionStartedByUs === true)\n                        await queryRunner.commitTransaction();\n                    // console.timeEnd(\"commit\");\n\n                } catch (error) {\n\n                    // rollback transaction if it was started by us\n                    if (isTransactionStartedByUs) {\n                        try {\n                            await queryRunner.rollbackTransaction();\n                        } catch (rollbackError) { }\n                    }\n                    throw error;\n                }\n\n            } finally {\n\n                // release query runner only if its created by us\n                if (!this.queryRunner)\n                    await queryRunner.release();\n            }\n        });\n    }\n\n}\n"],"sourceRoot":".."}