Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to manually set a primary key in Doctrine2

I am importing data into a new Symfony2 project using Doctrine2 ORM.

All new records should have an auto-generated primary key. However, for my import, I would like to preserve the existing primary keys.

I am using this as my Entity configuration:

  type: entity
  id:
    id:
      type: integer
      generator: { strategy: AUTO }

I have also created a setter for the id field in my entity class.

However, when I persist and flush this entity to the database, the key I manually set is not preserved.

What is the best workaround or solution for this?

like image 689
just_wes Avatar asked Nov 07 '11 21:11

just_wes


2 Answers

The following answer is not mine but OP's, which was posted in the question. I've moved it into this community wiki answer.


I stored a reference to the Connection object and used that to manually insert rows and update relations. This avoids the persister and identity generators altogether. It is also possible to use the Connection to wrap all of this work in a transaction.

Once you have executed the insert statements, you may then update the relations.

This is a good solution because it avoids any potential problems you may experience when swapping out your configuration on a live server.

In your init function:

  // Get the Connection
  $this->connection = $this->getContainer()->get('doctrine')->getEntityManager()->getConnection();

In your main body:

  // Loop over my array of old data adding records
  $this->connection->beginTransaction();

  foreach(array_slice($records, 1) as $record)
  {
    $this->addRecord($records[0], $record);
  }

  try
  {
    $this->connection->commit();
  }
  catch(Exception $e)
  {
    $output->writeln($e->getMessage());
    $this->connection->rollBack();

    exit(1);
  }

Create this function:

  // Add a record to the database using Connection
  protected function addRecord($columns, $oldRecord)
  {
    // Insert data into Record table
    $record = array();
    foreach($columns as $key => $column)
    {
      $record[$column] = $oldRecord[$key];
    }
    $record['id'] = $record['rkey'];
    // Insert the data
    $this->connection->insert('Record', $record);
  }
like image 55
Léo Lam Avatar answered Nov 01 '22 01:11

Léo Lam


You've likely already considered this, but my approach would be to set the generator strategy to 'none' for the import so you can manually import the existing id's in your client code. Then once the import is complete, change the generator strategy back to 'auto' to let the RDBMS take over from there. A conditional can determine whether the id setter is invoked. Good luck - let us know what you end up deciding to use.

like image 39
cantera Avatar answered Nov 01 '22 01:11

cantera