Calling Developers!
We are reenergizing our code contribution process! Learn More

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

Options
U03TE55TYE4
U03TE55TYE4 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:

Best Answer

  • Alberto Reyer
    Alberto Reyer Lead Spryker Solution Architect / Technical Director Posts: 690 🪐 - Explorer
    Answer ✓
    Options
    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

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

    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)

  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 🧑🏻‍🚀 - Cadet
    Options

    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'

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

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

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

    Or do you overwrite the id at some place

  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 🧑🏻‍🚀 - Cadet
    Options

    no, here is my code

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

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

  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 🧑🏻‍🚀 - Cadet
    Options

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

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

    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;
        }
    
  • Alberto Reyer
    Alberto Reyer Lead Spryker Solution Architect / Technical Director Posts: 690 🪐 - Explorer
    Options

    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();
    
  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 🧑🏻‍🚀 - Cadet
    Options

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


  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 🧑🏻‍🚀 - Cadet
    Options

    on the other side Call to undefined method: findOneOrCreate.

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

    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.

  • Alberto Reyer
    Alberto Reyer Lead Spryker Solution Architect / Technical Director Posts: 690 🪐 - Explorer
    Answer ✓
    Options
    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.

  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 🧑🏻‍🚀 - Cadet
    Options

    ok

  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 🧑🏻‍🚀 - Cadet
    Options

    Thanks for your time and help

  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 🧑🏻‍🚀 - Cadet
    Options

    May you please guide me one more thing

  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 🧑🏻‍🚀 - Cadet
    Options

    what I can improve in this class

  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 🧑🏻‍🚀 - Cadet
    Options
    <?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;
        }
    }
    
  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 🧑🏻‍🚀 - Cadet
    Options

    except the new operator.

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

    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.

  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 🧑🏻‍🚀 - Cadet
    Options

    Thanks for your time.