Generating next sequence value manually in Doctrin

2019-03-15 06:19发布

What would be the easiest way to generate nextval for some particular sequence with given name?

The annotation solution with specifying

 * @ORM\GeneratedValue(strategy="SEQUENCE")
 * @ORM\SequenceGenerator(sequenceName="sq_foobar", allocationSize="1", initialValue="1")

doesn't satisfy me, as long as there is some more complex logic involved: in some cases I need to retrieve nextval, in other - I would go with the value retrieved from another sources (not sequence).

So I hope there is a way to retrieve a sequence nextval manually in entity's constructor.

3条回答
倾城 Initia
2楼-- · 2019-03-15 06:41

There are two possibilities getting sequence nextval in Doctrine2:

  1. Use Doctrine ORM SequenceGenerator

    use Doctrine\ORM\Id\SequenceGenerator;
    $sequenceName = 'file_id_seq';
    $sequenceGenerator = new SequenceGenerator($sequenceName, 1);
    $newId = $sequenceGenerator->generate($entityManager, $entity);
    // $entity in this case is actually not used in generate() method, so you can give any empty object, or if you are not worried about editor/IDE warnings, you can also specify null
    
  2. Use native SQL

    $sequenceName = 'file_id_seq';
    $dbConnection = $entityManager->getConnection();
    $nextvalQuery = $dbConnection->getDatabasePlatform()->getSequenceNextValSQL($sequenceName);
    // $nextvalQuery is now following string "SELECT NEXTVAL('file_id_seq')"
    $newId = (int)$dbConnection->fetchColumn($nextvalQuery);
    
查看更多
姐就是有狂的资本
3楼-- · 2019-03-15 06:45

Just in case someone else lands on this question (like I did):
The pull request @Florian mentioned made it into doctrine now. Although documentation seems to still lack any information for the CUSTOM id generator strategy. Only part I found where CUSTOM option for IdGenerator is mentioned is at GeneratedValue description. If I missed it, please correct me in the comments.

Tough it can easily be implemented. Just create an class extending Doctrine\ORM\Id\AbstractIdGenerator\AbstractIdGenerator:

namespace My\Namespace;
use Doctrine\ORM\Id\AbstractIdGenerator;
class MyIdGenerator extends AbstractIdGenerator
{
    public function generate(\Doctrine\ORM\EntityManager $em, $entity)
    {
        // Create id here
        $id = <do some logic>;
        return $id;
    }
}

Then add it to your id description in the doctrine entity configuration (YAML example):

My\Bundle\Entity\MyEntity:
    type: entity
    id:
        id:
            type: bigint
            unique: true
            generator:
                strategy: CUSTOM
            customIdGenerator:
                class: 'My\Namespace\MyIdGenerator'
    fields:
        otherField: .... 

If you use Annotations instead of YAML, the entity configuration should look like this (untested):

/**
  * @Id 
  * @Column(type="integer")
  * @GeneratedValue(strategy="CUSTOM")
  * @CustomIdGenerator(class="My\Namespace\MyIdGenerator")
  */
  public $id;

And thats all ;)

查看更多
ら.Afraid
4楼-- · 2019-03-15 06:57

Then I think you should implement your own Identitfer Generator.

The easyest would be to override the Doctrine\ORM\Id\SequenceGenerator class to handle your specific case.

You then have to register this generator in the class metadata using Doctrine ORM API.

Some links: http://ranskills.wordpress.com/2011/05/26/how-to-add-a-custom-id-generation-strategy-to-doctrine-2-1/

https://github.com/doctrine/doctrine2/pull/206

查看更多
登录 后发表回答