【问题标题】:Doctrine 2.0- Will not update entityDoctrine 2.0- 不会更新实体
【发布时间】:2014-10-29 23:16:45
【问题描述】:

我正在为实体创建主键(字符串),并且正在尝试更新它。但是,当我调用 $em->persist() 然后 $em->flush() Doctrine 尝试插入新记录而不是更新当前存在的记录。

实体:

/**
* @Entity @Table(name="order_system_notes", indexes={@index(name="IDX_date", columns={"date"}),@index(name="IDX_note", columns={"note"})})
**/
class SystemNote{
    /**
    * @Id @Column(type="string")
    */
    protected $id;

    /**
    * @var \LL_Staging\Entities\Order|null the order this item belongs to (if any)
    * @ManyToOne(targetEntity="LL_Staging\Entities\Order", inversedBy="systemNotes",cascade={"persist","merge"})
    * @JoinColumn(name="order_id", referencedColumnName="id")
    */
    protected $order;

    /**
    * @Column(type="string", nullable=true) 
    */
    protected $user;
    // ... 

function __set($property, $value) {
    if(is_null($this->metadata)) $this->_initialize();
    $customSetter=LimeLightHelper::to_camel_case("set_".$property);
    if(method_exists($this,$customSetter))
        $this->$customSetter($value);
    elseif(property_exists($this,$property)){
        $fieldType = strtolower($this->metadata->getTypeOfField($property));            

        switch($fieldType){
            case "datetime":                
            try{

                $value = (is_object($value) && get_class($value)=="DateTime")?$value:new \DateTime($value);
            }
            catch(\Exception $e){
                user_error("Invalid DateTime Value $value for $property in ".get_class($this)." Assuming NULL",E_USER_NOTICE);
                $value=null;
            }
            $this->$property=$value;
            break;

            case null:
                if(in_array($property,array_keys($this->relationships)))
                    $this->_setRelatedField($property,$value);
                break;

            default:
                $this->$property=$value;   
                break;
        }

    }            
    else
        user_error("Trying to write non-existing property $property in ".get_class($this),E_USER_NOTICE);
}


    /**
    * Saves the entity, be it an existing record or a new one. Returns the tracked entity
    * 
    * @param Boolean (optional) if set to true, it will write this entity inmediately to the db. Defaults to FALSE
    * @return 
    */
function save($commit=false){
    $entity =(!is_null($this->id))?$this->entityManager->find('SystemNote',$this->id):null;

    if(!is_null($entity)){
        $entity=$this->entityManager->merge($this);
    }
    else 
        $entity=$this;


    $this->entityManager->persist($entity);

    if($commit)
        $this->entityManager->flush();

    return $entity;
}


}

假设我在数据库中已经有一个 id 为 123-321 的系统注释。

所以我这样做:

$a=new SystemNote();
$a->id="123-321";
//do more stuff with the SystemNote
$a->save(true); //this will give me a mysql error that says that the key already exists, and it can not be inserted. But I do not want to INSERT, I want to UPDATE

为什么会发生这种情况,我该如何解决?

【问题讨论】:

    标签: php symfony orm doctrine-orm doctrine


    【解决方案1】:

    1) 使用 getReference() 而不是 find() 来为您的实体获取代理,从而避免对数据库进行不必要的初步查询。

    $entity = $em->getReference("Entity", id);
    

    2)正确更新实体属性,使用setter修改实体的受保护/私有字段

    $entity->setStuff(...);
    $entity->setMoreStuff(...);
    

    3) 刷新到数据库

    $em->flush();
    

    您现有的实体现在应该相应地更新,同时保持所有未更改的字段不变。

    【讨论】:

      【解决方案2】:

      首先,在Doctrine2 中,管理器和数据层应该解耦。

      至于问题,您可能应该将persist 仅限于创建新的:

      $this->entityManager->persist($entity);
      

      需要更新时不要执行此行。

      【讨论】:

      • 在更新的情况下坚持下去不会有什么可怕的。但是当然可以不持久保存现有实体。
      • $this->entityManager->Merge() 会是这样吗?
      【解决方案3】:

      我只是在这里猜测,但我认为这是你的问题:

      $a->id="123-321";  
      

      当它是一个受保护的领域时,这条线是如何工作的?我希望您的 id 在此行之后实际上为 null,因此教义认为它实际上是一个新对象。

      【讨论】:

      • 尝试设置受保护的属性会导致致命错误,不是吗? php.net/manual/en/language.oop5.visibility.php
      • 是的,很抱歉,我没有复制执行该操作的通用设置器。代码已更新。 :) 问题仍然存在。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多