Updating record in database based on id through the propel save operation?

Posts: 32 🧑🏻‍🚀 - Cadet
edited June 2023 in Propel ORM

Need clue about the problem. I want to update the record in database based on id through the propel save operation but I am getting this error.

Cannot insert a value for auto-increment primary key (pyz_client_record.id)
Tagged:

Welcome!

It looks like you're new here. Sign in or register to get started.

Best Answer

  • Lead Spryker Solution Architect / Technical Director Posts: 690 🪐 - Explorer
    Answer ✓
    crudOperationEntity = new PyzCrudOperation();
            $crudOperationEntity->fromArray($crudOperationTransfer->modifiedToArray());
            $crudOperationEntity->save();
    

    It's exactly as I told, so please load the entity from the DB instead of creating it via new.
    A good rule of thumb is that you should never use new outside of DependencyProvider and Factories in Spryker, except for Transfers.

Answers

  • Lead Spryker Solution Architect / Technical Director Posts: 690 🪐 - Explorer

    Did you received the entity through a propel query (e.g.: PyzClientQuery::create()->findById(1)) or through an alternative way?

    Seems like the entity you are trying to save does not know that it already exists in the DB and does an insert instead of an update.

    If your case is to create a new entry in the DB please check if you have allowed to insert auto-increment values (allowPkInsert on the table definition: http://propelorm.org/documentation/reference/schema.html#table-attributes)

  • Posts: 32 🧑🏻‍🚀 - Cadet

    Thanks for your response.
    I have set the allowPkInsert and now it is throwing this error SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '22' for key 'PRIMARY'

  • Lead Spryker Solution Architect / Technical Director Posts: 690 🪐 - Explorer

    So I assume you have loaded/assembled the entity you try to save without using propel, could that be the case?

  • Lead Spryker Solution Architect / Technical Director Posts: 690 🪐 - Explorer

    Or do you overwrite the id at some place

  • Posts: 32 🧑🏻‍🚀 - Cadet

    no, here is my code

    $crudOperationTransfer->setId(22);
                $crudOperationTransfer->setName('Test update');
                $crudOperationTransfer->setDescription('description update');  
                $crudOperationTransfer->setStatus(false);          
                $crudOperationTransfer = $this->getFacade()->updateCrudOperationEntity($crudOperationTransfer);
    
  • Lead Spryker Solution Architect / Technical Director Posts: 690 🪐 - Explorer

    $crudOperationTransfer->setId(22); Where is the 22 coming from?

  • Posts: 32 🧑🏻‍🚀 - Cadet

    I set it hardcoded for the moment but it will be come through the post data.

  • Posts: 32 🧑🏻‍🚀 - Cadet
    edited August 2022

    Here is my method to update.

    may be I am doing something wrong in this

    public function updateEntity(CrudOperationTransfer $crudOperationTransfer): CrudOperationTransfer
        {
            $crudOperationEntity = new PyzCrudOperation();
            $crudOperationEntity->fromArray($crudOperationTransfer->modifiedToArray());
            $crudOperationEntity->save();
    
            $crudOperationTransfer->fromArray($crudOperationEntity->toArray(), true);
    
            return $crudOperationTransfer;
        }
    
  • Lead Spryker Solution Architect / Technical Director Posts: 690 🪐 - Explorer

    I assume inside updateCrudOperationEntity you just create an entity with new PyzClient fill it with data and call save() , could that be the case?
    If so please try to receive the entity first through

    $entity = PyzClientQuery::create()->filterById($transfer->getId())->findOneOrCreate();
    $entity->fromArray($transfer->toArray());
    $entity->save();
    
  • Posts: 32 🧑🏻‍🚀 - Cadet

    Well the save method in the PyzCleint actually used for both create and update the entity. Here is the code.


  • Posts: 32 🧑🏻‍🚀 - Cadet

    on the other side Call to undefined method: findOneOrCreate.

  • Lead Spryker Solution Architect / Technical Director Posts: 690 🪐 - Explorer

    I know, propel checks the isNew() method if an insert or an update should be executed during save.
    From the error you have it pretty much seems like propel is doing an insert (isNew() returns true), but should execute an update instead as you already have the entity in your DB and just want to update it.

    The most common case for this is that the entity was not loaded from the DB before, but created via new.

  • Lead Spryker Solution Architect / Technical Director Posts: 690 🪐 - Explorer
    Answer ✓
    crudOperationEntity = new PyzCrudOperation();
            $crudOperationEntity->fromArray($crudOperationTransfer->modifiedToArray());
            $crudOperationEntity->save();
    

    It's exactly as I told, so please load the entity from the DB instead of creating it via new.
    A good rule of thumb is that you should never use new outside of DependencyProvider and Factories in Spryker, except for Transfers.

  • Posts: 32 🧑🏻‍🚀 - Cadet

    ok

  • Posts: 32 🧑🏻‍🚀 - Cadet

    Thanks for your time and help

  • Posts: 32 🧑🏻‍🚀 - Cadet

    May you please guide me one more thing

  • Posts: 32 🧑🏻‍🚀 - Cadet

    what I can improve in this class

  • Posts: 32 🧑🏻‍🚀 - Cadet
    <?php
    
    namespace Pyz\Zed\CrudOperation\Persistence;
    
    use Generated\Shared\Transfer\CrudOperationTransfer;
    use Orm\Zed\CrudOperation\Persistence\PyzCrudOperation;
    use Spryker\Zed\Kernel\Persistence\AbstractEntityManager;
    use Orm\Zed\CrudOperation\Persistence\PyzCrudOperationQuery;
    
    /**
     * @method \Pyz\Zed\CrudOperation\Persistence\CrudOperationPersistenceFactory getFactory()
     */
    class CrudOperationEntityManager extends AbstractEntityManager implements CrudOperationEntityManagerInterface
    {
        /**
         * @param \Generated\Shared\Transfer\CrudOperationTransfer $crudOperationTransfer
         *
         * @return \Generated\Shared\Transfer\CrudOperationTransfer
         */
        public function saveEntity(CrudOperationTransfer $crudOperationTransfer): CrudOperationTransfer
        {
            $crudOperationEntity = new PyzCrudOperation();
            $crudOperationEntity->fromArray($crudOperationTransfer->modifiedToArray());
            $crudOperationEntity->save();
    
            $crudOperationTransfer->fromArray($crudOperationEntity->toArray(), true);
    
            return $crudOperationTransfer;
        }
    
        /**
         * @param \Generated\Shared\Transfer\CrudOperationTransfer $crudOperationTransfer
         *
         * @return \Generated\Shared\Transfer\CrudOperationTransfer
         */
        public function updateEntity(CrudOperationTransfer $crudOperationTransfer): CrudOperationTransfer
        {
            $crudOperationEntity = PyzCrudOperationQuery::create()->filterById($crudOperationTransfer->getId())->findOneOrCreate();
            $crudOperationEntity->fromArray($crudOperationTransfer->toArray());
            $crudOperationEntity->save();
    
            $crudOperationTransfer->fromArray($crudOperationEntity->toArray(), true);
    
            return $crudOperationTransfer;
        }
    
        /**
         * @param \Generated\Shared\Transfer\CrudOperationTransfer $crudOperationTransfer
         *
         * @return \Generated\Shared\Transfer\CrudOperationTransfer
         */
        public function deleteEntity(CrudOperationTransfer $crudOperationTransfer): CrudOperationTransfer
        {
            $crudOperationEntity = PyzCrudOperationQuery::create()->filterById($crudOperationTransfer->getId())->findOne();
            $crudOperationEntity->fromArray($crudOperationTransfer->modifiedToArray());
            $crudOperationEntity->delete();
    
            $crudOperationTransfer->fromArray($crudOperationEntity->toArray(), true);
    
            return $crudOperationTransfer;
        }
    }
    
  • Posts: 32 🧑🏻‍🚀 - Cadet

    except the new operator.

  • Lead Spryker Solution Architect / Technical Director Posts: 690 🪐 - Explorer

    deleteEntity() it makes no sense to fill the entity with data before it's deleted.
    For a little bit more efficiency you could skip the loading of the entity and directly delete it:

    PyzCrudOperationQuery::create()->filterById($crudOperationTransfer->delete();
    

    Please be aware that this happens on DB level, so no events are triggered. If you relay on events for this entity, for example to publish and synchronize it, you need to load the whole entity before you delete it.

    But I don't have time for a full code review here, sorry.

  • Posts: 32 🧑🏻‍🚀 - Cadet

    Thanks for your time.

Welcome!

It looks like you're new here. Sign in or register to get started.