MST

星途 面试题库

面试题:TypeScript 装饰器优化 TypeORM 实体查询性能及事务处理

在一个复杂的应用场景中,有多个 TypeORM 实体,例如 `Order`、`Product`、`Customer` 等,实体间存在多种关系。现在要求你通过 TypeScript 装饰器实现对实体查询性能的优化,同时确保在涉及多个实体操作时事务的一致性和隔离性,阐述你的设计思路并给出关键代码示例。
21.7万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 性能优化
    • 使用 TypeScript 装饰器为查询方法添加缓存机制。例如,对于一些不常变化的数据查询,可以缓存结果,避免重复数据库查询。
    • 利用装饰器对查询进行预处理,比如添加必要的索引查询条件,减少全表扫描。
  2. 事务一致性和隔离性
    • 使用 TypeORM 提供的事务管理功能,在装饰器中开启、提交或回滚事务。确保多个实体操作在同一个事务内,保证数据的一致性。
    • 通过设置合适的事务隔离级别(如 READ COMMITTEDREPEATABLE READ 等)来满足不同业务场景下的隔离性要求。

关键代码示例

  1. 性能优化装饰器
import { ReflectMetadata } from 'typescript';

// 缓存装饰器
const CacheQuery = () => {
    return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
        const originalMethod = descriptor.value;
        const cache: { [key: string]: any } = {};
        descriptor.value = async function (...args: any[]) {
            const key = args.toString();
            if (cache[key]) {
                return cache[key];
            }
            const result = await originalMethod.apply(this, args);
            cache[key] = result;
            return result;
        };
        return descriptor;
    };
};

// 索引优化装饰器示例(假设查询条件是第一个参数)
const IndexedQuery = () => {
    return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
        const originalMethod = descriptor.value;
        descriptor.value = async function (...args: any[]) {
            const queryBuilder = this.createQueryBuilder();
            // 假设第一个参数是查询条件
            const condition = args[0];
            if (condition && condition.id) {
                queryBuilder.where('entity.id = :id', { id: condition.id });
            }
            const result = await originalMethod.apply(this, args);
            return result;
        };
        return descriptor;
    };
};
  1. 事务管理装饰器
import { Transaction, TransactionManager, getConnection } from 'typeorm';

// 事务装饰器
const Transactional = (isolationLevel?: string) => {
    return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
        const originalMethod = descriptor.value;
        descriptor.value = async function (...args: any[]) {
            let manager;
            try {
                const connection = getConnection();
                if (isolationLevel) {
                    connection.transaction(isolationLevel, async (transactionManager) => {
                        manager = transactionManager;
                        await originalMethod.apply(this, [manager, ...args]);
                    });
                } else {
                    connection.transaction(async (transactionManager) => {
                        manager = transactionManager;
                        await originalMethod.apply(this, [manager, ...args]);
                    });
                }
            } catch (error) {
                if (manager) {
                    await manager.rollback();
                }
                throw error;
            }
        };
        return descriptor;
    };
};
  1. 使用示例
import { Entity, Column, PrimaryGeneratedColumn, Repository } from 'typeorm';

@Entity()
class Order {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    orderNumber: string;
}

class OrderRepository extends Repository<Order> {
    @CacheQuery()
    @IndexedQuery()
    @Transactional('REPEATABLE READ')
    async findOrderById(@TransactionManager() manager: any, id: number) {
        return manager.findOne(Order, { where: { id } });
    }
}

在上述代码中:

  • CacheQuery 装饰器实现了简单的缓存机制,避免重复查询。
  • IndexedQuery 装饰器对查询进行预处理,添加索引条件。
  • Transactional 装饰器用于管理事务,确保多个实体操作的一致性和通过设置隔离级别保证隔离性。在 OrderRepositoryfindOrderById 方法中,同时应用了这三个装饰器来满足性能优化和事务相关要求。