我遇到了Lifecycle Callback of Doctrine ORM的问题,这个问题没有在fetch-joined实体上执行,而是经常在延迟加载的实体上执行。
这是代码:
EntityA:
namespace AppBundle\Entity\EntityA;
use Doctrine\ORM\Mapping as ORM;
/**
* EntityA
* @ORM\Entity()
* @ORM\HasLifecycleCallbacks()
*/
class EntityA {
/**
* @var int
* @ORM\Id
*/
private $id;
/**
* @var string
*
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $name;
/**
* @var \Doctrine\Common\Collections\ArrayCollection
* @ORM\OneToMany(targetEntity="EntityB", mappedBy="EntityA", indexBy="name", cascade="all", orphanRemoval=true)
*/
private $entitiesB;
/**
* @var \Doctrine\Common\Collections\ArrayCollection
*/
private $myNotMappedField;
public function __construct() {
/*initializes here fields mapped by Doctrine to db*/
$this->name='';
$this->initNotMappedFields();
}
/**
* Here I initialize properties not handled by Doctrine
* @ORM\PostLoad()
*/
public function initNotMappedFields() {
$this->myNotMappedField=new \Doctrine\Common\Collections\ArrayCollection();
}
}
EntityB:
/**
* EntityB
* @ORM\Entity()
* @ORM\HasLifecycleCallbacks()
*/
class EntityB {
/**
* @var int
* @ORM\Id
*/
private $id;
/**
* @var string
*
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $name;
/**
* @var \Doctrine\Common\Collections\ArrayCollection
* @ORM\ManyToOne(targetEntity="EntityA", inversedBy="entitiesB")
*/
private $entityA
/**
* @var \Doctrine\Common\Collections\ArrayCollection
*/
private $myNotMappedField;
public function __construct() {
/*initializes here fields mapped by Doctrine to db*/
$this->name='';
$this->initNotMappedFields();
}
/**
* Here I initialize properties not handled by Doctrine
* @ORM\PostLoad()
*/
public function initNotMappedFields() {
$this->myNotMappedField=new \Doctrine\Common\Collections\ArrayCollection();
}
}
控制器:
// this works right:
// EntityA::initNotMappedFields() is properly called
$entityA = $this->getDoctrine()->getManager()->getRepository('AppBundle:EntityA')->findOneById(1);
// EntityB::initNotMappedFields() is properly called
$entityA->getEntitiesB();
// I want to fetch join EntityB into EntityA, to avoid
// multiple single SQL statements to be executed against the DB
// EntityA::initNotMappedFields() is called
$entityA = $this->getDoctrine()->getManager()->getRepository('AppBundle:EntityA')->createQueryBuilder('entA')
->addSelect(['entB'])
->andWhere('entA=:id')->setParameter('id', $id)
->leftJoin('entA.entitiesB', 'entB')
->getQuery()->getOneOrNullResult();
// EntityB::initNotMappedFields() is NOT called
$entityA->getEntitiesB();
我错过了什么?
答案 0 :(得分:1)
这是因为第一个示例将生成SQL查询以获取每个 EntityB ,然后将其加载到 EntityA 。如果A有10个B,那么您将获得10个额外的查询以获得在B上调用postLoad()
回调的每个B,因为EntityManager是构建 EntityB 的回调。请参阅documentation on the postLoad() event。
我要做的只是使用 EntityA 在 EntityB 上调用您的初始化:
/**
* Here I initialize properties not handled by Doctrine
* @ORM\PostLoad()
*/
public function initNotMappedFields()
{
$this->myNotMappedField = new \Doctrine\Common\Collections\ArrayCollection();
// the 'if' here is in case you load EntityA without joining EntityB
// so that you won't cause the extra queries if you don't want EntityB in there
if ($this->entitiesB) {
foreach ($this->entitiesB as $entityB) {
$entityB->initNotMappedFields();
}
}
}
答案 1 :(得分:1)
答案是'是的,任何加载操作都会触发postLoad事件'。
https://github.com/doctrine/doctrine2/issues/6568
对于将来从谷歌来到这里的人来说,问题出在我的应用程序中,我在PostLoad中使用了根实体在fetchjoined实体的PostLoad中设置的一些信息,但当然没有人可以保证我一个PostLoad在其他PostLoad之前或之后执行。
他们将很快或之后被执行。
所以使用的方法是这里描述的https://stackoverflow.com/a/45216602/7135824