You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Doctrine原生SQL递归查询无法返回parent_id列问题求助

问题

我编写了一个Doctrine方法findRecursiveByParentOrId,采用原生SQL递归CTE查询Division实体数据。已在ResultSetMapping中映射parent字段对应parent_id,实体也配置了parent关联parent_id的映射,但返回结果始终缺失parent_id列,尝试多种方法均未解决,需要确保parent_id在所有必要位置正确设置。

方法代码

public function findRecursiveByParentOrId(int $parentId, string $column): array
{
    $rsm = new ResultSetMapping();
    $rsm->addEntityResult(Division::class, 'div');
    $rsm->addFieldResult('div', 'id', 'id');
    $rsm->addFieldResult('div', 'name', 'name');
    $rsm->addFieldResult('div', 'description', 'description');
    $rsm->addFieldResult('div', 'parent', 'parent_id');

    $query = $this->getEntityManager()->createNativeQuery('
        WITH RECURSIVE cte (id, name, description, parent_id) AS (
            SELECT id, name, description, parent_id FROM division
            WHERE ' . $column . ' = ?
            UNION ALL
                SELECT d.id, d.name, d.description, d.parent_id FROM division d
                INNER JOIN cte
                    ON d.parent_id = cte.id
        )
        SELECT * FROM cte;
    ', $rsm);
    $query->setParameter(1, $parentId);

    return $query->getArrayResult();
}

实体关联配置

/**
 * @ORM\ManyToOne(targetEntity=Division::class, inversedBy="children")
 * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", nullable=true)
 */
private ?Division $parent = null;

返回结果示例

array:5 [▼
  0 => array:3 [▼
    "id" => 1
    "name" => "Personal Abteilung"
    "description" => "Personal Abteilung"
  ]...
解决方案

问题核心在于ResultSetMapping的映射逻辑和getArrayResult()的返回规则,修正步骤如下:

  1. 显式映射parent_id为标量字段
    你当前用addFieldResult把实体的parent关联属性映射到parent_id列,但getArrayResult()只会返回实体的标量字段,不会自动将关联属性转换为对应的外键值。要在数组结果中拿到parent_id,必须单独用addScalarResult显式映射该列:
// 在ResultSetMapping中添加这一行
$rsm->addScalarResult('parent_id', 'parent_id');
  1. 保留关联映射(可选)
    如果后续需要获取Division实体对象而非数组,addFieldResult('div', 'parent', 'parent_id')的映射是必要的,但它不会影响数组结果的字段,所以可以保留。

  2. 修改后的完整方法

public function findRecursiveByParentOrId(int $parentId, string $column): array
{
    $rsm = new ResultSetMapping();
    $rsm->addEntityResult(Division::class, 'div');
    $rsm->addFieldResult('div', 'id', 'id');
    $rsm->addFieldResult('div', 'name', 'name');
    $rsm->addFieldResult('div', 'description', 'description');
    // 显式映射parent_id到结果数组
    $rsm->addScalarResult('parent_id', 'parent_id');
    // 关联映射用于实体对象的parent属性(按需保留)
    $rsm->addFieldResult('div', 'parent', 'parent_id');

    $query = $this->getEntityManager()->createNativeQuery('
        WITH RECURSIVE cte (id, name, description, parent_id) AS (
            SELECT id, name, description, parent_id FROM division
            WHERE ' . $column . ' = ?
            UNION ALL
                SELECT d.id, d.name, d.description, d.parent_id FROM division d
                INNER JOIN cte
                    ON d.parent_id = cte.id
        )
        SELECT * FROM cte;
    ', $rsm);
    $query->setParameter(1, $parentId);

    return $query->getArrayResult();
}

修改后,返回的数组结果就会包含parent_id字段。


内容的提问来源于stack exchange,提问作者Kleber Salgado

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 14:33:09