【问题标题】:TypeORM discards where clauseTypeORM 丢弃 where 子句
【发布时间】:2022-01-10 15:48:55
【问题描述】:

我正在扩展和改进由另一个(不可用)开发人员构建的 API。它使用 TypeORM,我们使用 PostgreSQL 数据库。

这是我打算修改的文件开头的“功能框架”(不知道正确的术语):

type Handler = RequestHandler<ParamsDictionary, any, any, Query>;

const createNew = <TReq, TParent, TChild, TRes = DataNode.DataNode>(
    parentEntityClass: ObjectType<TParent>,
    childPropertyName: string,
    parentPropertyName: string,
    reqValidator: (body: TReq) => boolean,
    constraintSelector: (body: TReq) => string | number | Date | ObjectID,
    dataMapper: (body: TReq, res: Response) => Promise<TChild>,
    responseSerializer?: (
        entity: TChild,
        req?: Request<ParamsDictionary, any, any, Query>
    ) => Promise<TRes>
): Handler => asyncHandler(async (req, res) => {
    const logger = req.getLogger();
    const db = req.getDbContext();

    const reqBody = RequestUtility.getJsonAndValidate<TReq>(
        req,
        reqValidator,
        logger
    );

    const child = await dataMapper(reqBody, res);

    if (parentEntityClass) {
        const parent = await QueryUtility.findOneOrFail(
            db,
            parentEntityClass,
            constraintSelector(reqBody)
        );

        const childsParentWrapped: { [k: string]: any } = {};

        logger.debug(`checking if child refs parent ${JSON.stringify({
            childProps: Object.getOwnPropertyNames(child),
            prop: parentPropertyName
        })}`);

        if (Object.getOwnPropertyNames(child).includes(parentPropertyName) ||
            Object.getOwnPropertyNames(child).includes(`__${parentPropertyName}__`)) {
            childsParentWrapped[parentPropertyName] = Promise.resolve(parent);

            Object.assign(child, childsParentWrapped);
        }

        if (Object.getOwnPropertyNames(parent).includes(childPropertyName)) {
            await QueryUtility.addChild(db, parentEntityClass, childPropertyName, parent, child);
        } else {
            await db.manager.save(child);
        }
    } else {
        await db.manager.save(child);
    }

    const result = await responseSerializer(child, req);

    res.json(result);
});

这是我打算修改的函数(同一文件的另一部分)。

type NewFile = { fileName: string};
type CreatedNewFileResponse = { uploadUrl: string; file: DataNode.DataNode };

export const createNewFile: Handler = createNew<NewFile, EUser, EFile, CreatedNewFileResponse>(
    EUser,
    "",
    "user",
    (body) => body.fileName ? true : false,
    (body) => null,
    async (body, res) => {
        const newFile = new EFile();
        const fileType = body.fileName.toLowerCase().split(/\.(?=[^\.]+$)/);
        if (['jpg', 'jpeg', 'gif', 'bmp', 'png'].includes(fileType[1])){
            newFile.fileName = body.fileName;
            newFile.fileType = 'image';
            newFile.storageProvider = "internal-storage";
            newFile.isMarkedForDeletion = false;
            const id = JSON.parse(JSON.stringify(res.locals.jwtPayload.id));
            newFile.user = Promise.resolve(
                        await getRepository(EUser).findOne({where: { id } })    
                        );
            return newFile;

        } else if (['avi', 'wmv', 'mp4', 'mkv', 'flv', 'mov'].includes(fileType[1])) {
            newFile.fileName = body.fileName;
            newFile.fileType = 'video';
            newFile.storageProvider = "internal-storage";
            newFile.isMarkedForDeletion = false;
            const id = JSON.parse(JSON.stringify(res.locals.jwtPayload.id));
            newFile.user = Promise.resolve(
                        await getRepository(EUser).findOne({where: { id } })    
                        );

            return newFile;

        } else if (['ogg', 'wma', 'wave', 'mp3', 'wav', 'm4a'].includes(fileType[1])) {
            newFile.fileName = body.fileName;
            newFile.fileType = 'audio';
            newFile.storageProvider = "internal-storage";
            newFile.isMarkedForDeletion = false;
            const id = JSON.parse(JSON.stringify(res.locals.jwtPayload.id));
            newFile.user = Promise.resolve(
                        await getRepository(EUser).findOne({where: { id } })    
                        );

            return newFile;

        } else {
            throw errors.create(BadRequestError);
        }
    },
    async (newFile, req) => {
        const minioContext = req.getMinioContext();
        let uploadUrl = await minioContext.client.presignedUrl(
            "PUT",
            minioContext.bucket,
            newFile.fileName,
            7 * 24 * 60 * 60,
            { query: {}, headers: { host: req.hostname } }
        );
        uploadUrl = uploadUrl.replace(
            `${minioContext.config.host}:${minioContext.config.port}`,
            req.hostname
        ).replace("localhost", `${minioContext.config.minioUrl}`).replace("http", "https")

        return {
            uploadUrl,
            file: await DataNode.fromFile(newFile)
        };
    }
);

该函数有效(因为它没有错误地达到其目的)并在数据库中插入预期的行。但是在声明newFile.user = JSON.parse(JSON.stringify(res.locals.jwtPayload.id)); 的行上,虽然它确实检索到了正确的信息(它从 JWT 返回 id),但正如我们在 PostgreSQL 日志中看到的那样,该信息被丢弃,然后利用用户表中的第一行(这意味着,不使用我们检索到的 id):

2020-12-04 18:39:20.395 UTC [690] DETAIL:  parameters: $1 = '1'
2020-12-04 18:39:20.405 UTC [690] LOG:  execute <unnamed>: SELECT "User"."id" AS "User_id", "User"."created" AS "User_created", "User"."updatedAt" AS "User_updatedAt", "User"."username" AS "User_username", "User"."password" AS "User_password", "User"."role" AS "User_role", "User"."firstName" AS "User_firstName", "User"."lastName" AS "User_lastName", "User"."email" AS "User_email" FROM "Users" "User" WHERE "User"."id" = $1 LIMIT 1
2020-12-04 18:39:20.405 UTC [690] DETAIL:  parameters: $1 = '1'
2020-12-04 18:39:20.413 UTC [690] LOG:  statement: SELECT "User"."id" AS "User_id", "User"."created" AS "User_created", "User"."updatedAt" AS "User_updatedAt", "User"."username" AS "User_username", "User"."password" AS "User_password", "User"."role" AS "User_role", "User"."firstName" AS "User_firstName", "User"."lastName" AS "User_lastName", "User"."email" AS "User_email" FROM "Users" "User" LIMIT 1
2020-12-04 18:39:20.420 UTC [690] LOG:  statement: START TRANSACTION
2020-12-04 18:39:20.429 UTC [690] LOG:  execute <unnamed>: INSERT INTO "Files"("fileName", "fileType", "storageProvider", "isMarkedForDeletion", "userId") VALUES ($1, $2, $3, $4, $5) RETURNING "id", "created", "updatedAt"
2020-12-04 18:39:20.429 UTC [690] DETAIL:  parameters: $1 = 'test.jpg', $2 = 'image', $3 = 'internal-storage', $4 = 'f', $5 = '2'
2020-12-04 18:39:20.433 UTC [690] LOG:  statement: COMMIT

正如您在日志片段的第 2 行看到的,where 子句受到尊重。但是当我们到达将信息插入数据库的部分(代码片段的第 4 行)时,where 子句被丢弃。

我不知道单独调试这个。 非常感谢任何帮助。

【问题讨论】:

    标签: typescript postgresql typeorm


    【解决方案1】:

    解决了。

    我最终将“用户”更改为“”。

    以某种方式解决了问题,现在到达我的 postgres 的查询包含我想要的 userId。

    还是谢谢。

    【讨论】:

      【解决方案2】:

      您似乎只指定 where 子句中的列而不是值。假设 id 的值在一个名为 'id' 的变量中,那么 find 语句应该是这样的: await getRepository(EUser).findOne({where: { id: id } })

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-05
        • 1970-01-01
        • 2021-12-11
        • 2020-10-27
        • 2021-08-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多