我遇到了在我的Doctrine实体中填充关联的问题。即使设置为预先加载,实体也会完全填充关联的单个例外。我有其他类似的协会工作,所以我怀疑有一些基本的理解,我在这里失踪。
我在这里要做的是在$s
实体中使用S
对象填充s
,在查询中称为SHealth
。我提前为命名道歉,但我不得不删除任何可能识别的内容,因为这是专有代码的一部分。
以下是我的// -------------------------------------------------------------------
// ENTITY FOR SHealth
// -------------------------------------------------------------------
/**
* Used for tracking the current health of shares.
* @Entity(repositoryClass="SHealthRepository")
* @Table(name="s_health")
*/
class SHealth
{
/**
* @Id
* @Column(type="integer", name="s_id")
*/
protected $sId;
/**
* @Id
* @Column(type="integer", name="l_id")
*/
protected $lId;
/**
* @Id
* @Column(type="smallint", name="s_type")
*/
protected $sType;
/**
* @Id
* @Column(type="smallint", name="s_subtype")
*/
protected $sSubtype;
/**
* @Column(type="smallint", name="health_status")
*/
protected $healthStatus;
/**
* @Column(type="datetime", name="update_time")
*/
protected $updateTime;
/**
* Scalar value
*/
protected $active;
/**
* @ManyToOne(targetEntity="S")
* @JoinColumns({
* @JoinColumn(name="l_id", referencedColumnName="l_id"),
* @JoinColumn(name="s_id", referencedColumnName="id")
* })
*/
protected $s;
// [Accessors and mutators omitted]
}
实体类的大部分内容:
// -------------------------------------------------------------------
// Repository fetch function
// -------------------------------------------------------------------
$rtime_check = !$include_rtimed ? " AND s.rtime IS NULL" : "";
$limit_check = $limit > 0 ? " LIMIT " . $limit : "";
$sql = "SELECT
s.l_id,
s.id AS s_id,
COALESCE(s_health.s_type, s.type) AS s_type,
COALESCE(s_health.s_subtype, 0) AS s_subtype,
s_health.health_status,
s_health.update_time,
(s.enabled AND
COALESCE(orsr.status, orsh.status, 0) > 0) AS active
FROM s
LEFT JOIN s_health ON
s.l_id = s_health.l_id AND
s.id = s_health.s_id AND
s.type = s_health.s_type AND
s_health.s_subtype = 0
LEFT JOIN orsr ON
s.l_id = orsr.l_id AND
s.se_id = orsr.se_id AND
orsr.status IN ([omitted])
LEFT JOIN orsh ON
s.l_id = orsh.l_id AND
s.id = orsh.s_id AND
orsh.status IN ([omitted])
WHERE s.l_id IN (:d_ids)
{$rtime_check}
GROUP BY s.l_id, s.id
{$limit_check}";
// Map the SQL result columns to class properties.
$rsm = new ResultSetMappingBuilder($this->_em);
$rsm->addRootEntityFromClassMetadata(SHealth::class, 's_alias');
$rsm->addScalarResult('active', 'active');
$query = $this->_em->createNativeQuery($sql, $rsm);
$query->setParameter("d_ids", $d_ids);
$results = $query->getResult();
// Inject aggregate function results into the resulting object.
$health_objects = [];
foreach ($results as $result)
{
$health_object = $result[0];
$health_object->setActive($result['active']);
$health_objects[] = $health_object;
}
return $health_objects;
以下是相关存储库类的片段:
S
最后,这是// -------------------------------------------------------------------
// ENTITY FOR S
// -------------------------------------------------------------------
/**
* @Entity
* @Table(name="s")
*/
class S
{
/**
* @Id
* @Column(type="integer")
*/
protected $id;
/**
* @Id
* @Column(type="integer", name="l_id")
*/
protected $lId;
/**
* @Column(type="integer", name="se_id")
*/
protected $seId;
/**
* @Column(type="smallint")
*/
protected $type;
/**
* @Column(type="boolean")
*/
protected $enabled;
/**
* @Column(type="datetime")
*/
protected $rtime;
// [Accessors and mutators omitted]
}
类,删除了一些成员:
.NET Command Line Tools (1.0.0-preview2-1-003177)
我拥有所有必需的getter和setter,并且所有必需的数据库数据都存在于两个表中,因此连接列不会出现任何问题。
答案 0 :(得分:0)
如果您的加入列是实体标识符的一部分,您应该尝试这样一次:
1)使用/**
* @Id
* @ManyToOne(targetEntity="S")
* @JoinColumns({
* @JoinColumn(name="l_id", referencedColumnName="l_id"),
* @JoinColumn(name="s_id", referencedColumnName="id")
* })
*/
protected $s;
注释将关联标记为标识符的一部分:
/**
* @Id
* @Column(type="integer", name="s_id")
*/
protected $sId;
/**
* @Id
* @Column(type="integer", name="l_id")
*/
protected $lId;
2)删除其他两列:
Email_Body = & PN & " has failed for ap
答案 1 :(得分:0)
我仍然不完全确定是什么阻止了原生查询的工作,但我已经改变了解决这个问题的方向。我发布的答案是,其他人将来会遇到类似的问题。
我最后做的是完全删除"
存储库,而只是使用SHealth
存储库。我走这条路是因为我的原生查询主要是从S
中选择。因此,我没有尝试将select s
的结果放入s
实体(使用本机查询),而是使用了来自关系另一端的更简单的DQL查询。 / p>
以下是我的新存储库获取功能,这次是在sHealth
存储库中,它与问题中的本机查询基本相同:
S
我将此字段添加到我的$query_builder = $this->_em->createQueryBuilder();
$query_builder->select('s, CASE WHEN s.enabled = TRUE AND COALESCE(orsr.status, orsh.status, 0) != 0 THEN TRUE ELSE FALSE END AS active')
->from(S::class, 's')
->leftJoin(
ORSR::class,
'orsr',
\Doctrine\ORM\Query\Expr\Join::WITH,
"s.lId = orsr.lId AND
s.seId = orsr.seId AND
orsr.status IN ([omitted])"
)
->leftJoin(
ORSH::class,
'orsh',
\Doctrine\ORM\Query\Expr\Join::WITH,
"s.lId = orsh.lId AND
s.id = orsh.sId AND
orsh.status IN ([omitted])"
)
->where('s.lId IN (:d_ids)')
->setParameter('d_ids', $d_ids);
// If rtimed items were not requested, exclude them.
if (!$include_rtimed)
{
$query_builder->andWhere(
$query_builder->expr()->isNull('s.rtime')
);
}
// Apply limit if specified.
if (!is_null($limit))
{
$query_builder->setMaxResults($limit);
}
$s_list = $query_builder->getQuery()->getResult();
// Inject aggregate function results into the resulting object.
$results = [];
foreach ($s_list as $row)
{
$this_s = $row[0];
$this_s->setActive($row['active']);
$results[] = $this_s;
}
return $results;
实体:
S
而且,我改变了/**
* @OneToMany(targetEntity="SHealth", mappedBy="s")
* @JoinColumns({
* @JoinColumn(name="l_id", referencedColumnName="l_id"),
* @JoinColumn(name="id", referencedColumnName="s_id")
* })
*/
protected $health;
的关联以反转sHealth
中的关联:
S
故事的寓意是,不是试图使用本机查询为关联执行正确的连接,而是反转实体并离开连接(在这种情况下通过使用DQL的关联)而不是。