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

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 βœ“
    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

    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

    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

    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

    Or do you overwrite the id at some place

  • U03TE55TYE4
    U03TE55TYE4 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);
    
  • Alberto Reyer
    Alberto Reyer Lead Spryker Solution Architect / Technical Director Posts: 690 πŸͺ - Explorer

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

  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 πŸ§‘πŸ»β€πŸš€ - Cadet

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

  • U03TE55TYE4
    U03TE55TYE4 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;
        }
    
  • Alberto Reyer
    Alberto Reyer 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();
    
  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 πŸ§‘πŸ»β€πŸš€ - Cadet

    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

    on the other side Call to undefined method: findOneOrCreate.

  • Alberto Reyer
    Alberto Reyer 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.

  • Alberto Reyer
    Alberto Reyer 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.

  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 πŸ§‘πŸ»β€πŸš€ - Cadet

    ok

  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 πŸ§‘πŸ»β€πŸš€ - Cadet

    Thanks for your time and help

  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 πŸ§‘πŸ»β€πŸš€ - Cadet

    May you please guide me one more thing

  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 πŸ§‘πŸ»β€πŸš€ - Cadet

    what I can improve in this class

  • U03TE55TYE4
    U03TE55TYE4 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;
        }
    }
    
  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 πŸ§‘πŸ»β€πŸš€ - Cadet

    except the new operator.

  • Alberto Reyer
    Alberto Reyer 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.

  • U03TE55TYE4
    U03TE55TYE4 Posts: 32 πŸ§‘πŸ»β€πŸš€ - Cadet

    Thanks for your time.