当有空对象时,如何处理学说的懒惰加载?

编程入门 行业动态 更新时间:2024-10-18 01:32:40
本文介绍了当有空对象时,如何处理学说的懒惰加载?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我有一个问题,正确的方式来处理学说的惰性加载机制。我有一个实体通过@ManyToOne引用另一个实体:

class Entity { ... / ** * @ManyToOne(targetEntity =AnotherEntity) * @JoinColumn(name =anotherEntityId,referencedColumnName =id) * / protected $ anotherEntity ; ... } class AnotherEntity { / ** * @var integer $ id * @Column(name = id,type =integer,nullable = false) * @Id * @GeneratedValue(strategy =IDENTITY) * / private $ id; / ** * @var string $ someValue * @Column(name =someValue,type =string) * / private $ someValue; ... }

Doctrine现在为AnotherEntity生成代理,实现懒惰加载它的getter:

public function getSomeValue() { $ this-> __ load (); return parent :: getSomeValue(); }

如果我现在有一些Entity的实例没有引用对应的AnotherEntity($ anotherEntityId为0或null)。然后,教义似乎生成AnotherEntity的一个null对象,并使所有Entity对象的$ anotherEntity变量指向它。空对象是未初始化的,因为我们想要延迟加载。 我现在得到一个EntityNotFoundException当我这样做:

$ entiy-> getAnotherEntity() - > getSomeValue ();

太好了! AnotherEntity I访问不存在于数据库中,所以我得到这个异常。 但是当我对第二个Entity(和所有其他的实体)做同样的事情时,我没有得到这个异常,因为它们都指向AnotherEntity和doctrine的同一个实例,它被标记为在第一个调用中被初始化。所以现在我正在访问一个逻辑上不存在的对象,但没有任何异常 - 我只是从getSomeValue()获取未初始化的变量,例如一个空字符串。

你有什么想法可以让我的应用程序认识到该对象不存在,而不仅仅是接受空值吗?

解决方案

我想这是一个教条的错误,因为代理被标记为初始化,即使不是当EntityNotFoundException被抛出时。以下是每个代理产生的代码原则:

public function __load() { if !$ this-> __ isInitialized__&& $ this-> _entityPersister){ $ this-> __ isInitialized__ = true; if(method_exists($ this,__wakeup)){ //在__isInitialized__之后调用此函数以避免无限递归 //但在加载之前要模拟什么ClassMetadata :: newInstance () //提供。 $ this-> __ wakeup(); } if($ this-> _entityPersister-> load($ this-> _identifier,$ this)=== null){ throw new \ Doctrine\ORM\EntityNotFoundException(); } unset($ this-> _entityPersister,$ this-> _identifier); } }

在ProxyFactory文件中,您可以找到此代码在抛出异常之前添加以下行解决了问题:

$ this-> __ isInitialized__ = false;

有了这个,你每次需要时都会得到例外。

tw:原则人们已经自己讨论了这个问题,但修补程序似乎不在当前的版本中: github/doctrine/doctrine2/pull/364

i have a question about the correct way to handle doctrine's lazy loading mechanism. I have an entity that references another one via @ManyToOne:

class Entity { ... /** * @ManyToOne(targetEntity="AnotherEntity") * @JoinColumn(name="anotherEntityId", referencedColumnName="id") */ protected $anotherEntity; ... } class AnotherEntity { /** * @var integer $id * @Column(name="id", type="integer", nullable=false) * @Id * @GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var string $someValue * @Column(name="someValue", type="string") */ private $someValue; ... }

Doctrine now generates a proxy for AnotherEntity that implements lazy loading on its getters:

public function getSomeValue() { $this->__load(); return parent::getSomeValue(); }

If I now have some instances of Entity that do not have a reference counterpart of AnotherEntity ($anotherEntityId is 0 or null). Then doctrine seems to generate ONE null-Object of AnotherEntity and makes the $anotherEntity variables of all Entity object point to it. The null-object is uninitialized since we want lazy loading. I now get an EntityNotFoundException when I do this:

$entiy->getAnotherEntity()->getSomeValue();

That's great! The AnotherEntity I access does not exist in the database and so I get this exception. BUT when I do the same with the second Entity (and all others afterwards) I do not get this exception, since they are all pointing to the same instance of AnotherEntity and doctrine marked it as initialized in the first call. So now I'm accessing an object that does not exist logically but do not get any exception - I just get the uninitialized variable from getSomeValue(), e.g. an empty string.

Do you have any idea how I can make my application to recognize that the object does not exist instead of just accepting the empty value?

解决方案

I guess that's a bug of doctrine, since the proxy is marked as initialized even if it is not when the EntityNotFoundException is thrown. Here is the code doctrine generates for each proxy:

public function __load() { if (!$this->__isInitialized__ && $this->_entityPersister) { $this->__isInitialized__ = true; if (method_exists($this, "__wakeup")) { // call this after __isInitialized__to avoid infinite recursion // but before loading to emulate what ClassMetadata::newInstance() // provides. $this->__wakeup(); } if ($this->_entityPersister->load($this->_identifier, $this) === null) { throw new \Doctrine\ORM\EntityNotFoundException(); } unset($this->_entityPersister, $this->_identifier); } }

In the file ProxyFactory you can find this code and by adding the following line just before the exception is thrown the problem is solved:

$this->__isInitialized__ = false;

With this you get the exception everytime it's needed.

Btw: the doctrine people already discussed that issue themselves but the fix does not seem to be in the current version: github/doctrine/doctrine2/pull/364

更多推荐

当有空对象时,如何处理学说的懒惰加载?

本文发布于:2023-11-26 22:59:26,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1635553.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:学说   如何处理   懒惰   加载   对象

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!