【问题标题】:Doctrine2: related keysDoctrine2:相关键
【发布时间】:2011-09-15 02:37:23
【问题描述】:

我有下表(类型、ID、标题)。

当创建新对象并且 type=1 id 应该是 1 时,下一个 type=1 的对象 id=2... 但是当我创建 type=2 的对象时,id 应该是 1。

我如何使用 Doctrine2 和 Symfony2 做到这一点?

【问题讨论】:

  • 你的意思我不是很清楚。您是否正在处理两个独立的实体并试图将它们存储在同一个表中?如果是,为什么?
  • 不,它是一个实体。 'type' 是类别,每个类别中的 id 都应该增加。独立于他人。
  • 如果 id 是主键,则不能在同一个表中执行此操作。我想你可以有一个 category_id 字段并以编程方式为每个类别构建它,但据我所知,Doctrine 不会开箱即用地支持它。
  • id 是示例字段名称

标签: php doctrine-orm symfony


【解决方案1】:

就像其他人所说的那样,Doctrine 2 并没有开箱即用地做到这一点。通常的做法是使 ID 字段自动递增和主键,在这种情况下这是不可能的。主键必须是唯一的。

话虽如此,解决方案可能是使用实体管理来查找类型为所选类型的 ID 的最大值,并将该值增加 1。

例如:

// Retrieve the current maximum ID for the selected type
$id = $em->createQuery("SELECT MAX(e.id) AS id FROM Entities\entity e WHERE e.type = ?1")
  ->setParameter(1, $type)
  ->getSingleScalarResult();

// Set your current entity's ID
$entity->setId(++$id);

// Save the entity
...

【讨论】:

  • 并发呢?当两个请求尝试同时创建一个实体并且它们都“选择最大值”并获取相同的 id 时会发生什么情况,从而创建了两个具有相同 id 的实体(除非您设置了唯一属性,这会在插入时引发异常无论如何)。
【解决方案2】:

使用MAX(id) 不是最好的解决方案,因为它可能会导致一些问题。如果您删除给定类别中的最新记录然后添加新记录会怎样?它将具有与以前相同的 ID。

  1. 复合主键(typeid)目前还没有被 Doctrine 很好地处理,所以我建议创建一个经典的主键:整数,自增键(至少对于 Doctrine 的使用)。此外,您始终可以在 typetype_id 列上拥有唯一索引,并随时使用它。
  2. type_id 列的自动增量创建您自己的实现:

    1. 由于type_idType 相关联,您可以在type 表:next_auto_increment 中存储附加列,该表存储将用于下一条记录的值。
    2. 每当您在表中创建新记录时,只需从 type 表中为其选择值 type_id

      $type = ...;
      
      $entity = new Entity();
      $entity->setType($type);
      $entity->setTypeId($type->getNextAutoIncrement()); 
      // btw: typeId is not a very best name
      
      $em->persist($entity);
      
    3. 每次插入记录时,您还需要在数据库中使用触发器来增加 next_auto_increment 的值(MySQL 示例):

      DELIMITER $$
      CREATE TRIGGER increment_ai AFTER insert ON entity_table FOR EACH ROW BEGIN
          UPDATE type_table 
          SET next_auto_increment = next_auto_increment + 1 
          WHERE id = NEW.type;
      END$$
      DELIMITER ;
      

【讨论】:

    【解决方案3】:

    正如我上面的 cmets 所指出的,我认为没有直接支持您尝试开箱即用的操作。但是,我认为您应该能够使用class table inheritance 来近似它,其中每个type 类别都是它自己的实体,它在类表上共享公共数据并跟踪自己的索引。

    【讨论】:

    • 我不能使用表继承,因为它们应该动态创建。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-05
    • 1970-01-01
    • 1970-01-01
    • 2011-12-29
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多