【问题标题】:when flush() primary key does not get inserted当 flush() 主键没有被插入时
【发布时间】:2015-03-03 19:40:17
【问题描述】:

我正在开发一个 PHP 项目,使用 Symfony 2 和 Doctrine 作为 ORM。当我持久化并刷新对象时,主键列甚至不在插入 SQL DML 语句中,当然会引发错误。 ID 是一个生成的值,使用 PHP 的 uniqid。 我将提供实体和控制器的代码sn-p。

/**
* Metrics
*
* @ORM\Table(name="metrics", indexes={@ORM\Index(name="metrics_assignedTo_fk",     columns={"assignedTo"}), @ORM\Index(name="metrics_ui_fk", columns={"ui"})})
* @ORM\Entity
*/
class Metrics
{
/**
 * @var string
 *
 * @ORM\Column(name="baseline", type="string", length=15, nullable=true)
 */
private $baseline;

/**
 * @var string
 *
 * @ORM\Column(name="testEvent", type="string", length=40, nullable=true)
 */
private $testevent;

/**
 * @var string
 *
 * @ORM\Column(name="status", type="string", length=20, nullable=true)
 */
private $status;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="date", type="date", nullable=true)
 */
private $date;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="shotStart", type="datetime", nullable=true)
 */
private $shotstart;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="shotEnd", type="datetime", nullable=true)
 */
private $shotend;

/**
 * @var string
 *
 * @ORM\Column(name="c2p", type="string", length=10, nullable=true)
 */
private $c2p;

/**
 * @var string
 *
 * @ORM\Column(name="notes", type="string", length=200, nullable=true)
 */
private $notes;

/**
 * @var string
 *
 * @ORM\Column(name="uniqueid", type="string", length=100, nullable=false)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="NONE")
 */
private $uniqueid;

/**
 * @var \fti\webBundle\Entity\Employees
 *
 * @ORM\ManyToOne(targetEntity="fti\webBundle\Entity\Employees")
 * @ORM\JoinColumns({
 *   @ORM\JoinColumn(name="ui", referencedColumnName="empid")
 * })
 */
private $ui;
}

为了清楚起见,我省略了 getter 和 setter。

$shotObj->setShotstart(date_create($postData['start']));
                $shotObj->setShotend(date_create($postData['end']));
                $shotObj->setC2p($postData['c2p']);
                $shotObj->setUniqueid((uniqid('', true)));


            $shotForm = $this->createFormBuilder($shotObj)
                ->add('status', 'choice', array(
                    'choices' => array(
                        'changed' => 'Changed',
                        'canceled' => 'Canceled',
                        'added' => 'Added'
                    ),
                    'multiple' => false,
                    'expanded' => false,
                    'required' => false,
                    'placeholder' => '-'
                ))
                ->add('c2p', 'hidden')
                ->add('shotStart', 'datetime', array(
                    'attr' => array(
                        'style' => 'display: none'
                    )
                ))
                ->add('shotEnd', 'datetime', array(
                    'attr' => array(
                        'style' => 'display: none'
                    )
                ))
                ->add('uniqueid', 'hidden')
                ->add('baseline', 'choice', array(
                    'choices' => $this->buildBLChoices(),
                    'multiple' => false,
                    'expanded' => false,
                    'placeholder' => '-'
                ))
                ->add('testevent', 'choice', array(
                    'choices' => $this->buildTEChoices(),
                    'multiple' => false,
                    'expanded' => false,
                    'required' => false,
                    'placeholder' => '-'
                ))
                ->add('test', 'text', array(
                    'mapped' => false,
                    'required' => false
                ))
                ->add('assignedTo', 'entity', array(
                    'class' => 'ftiwebBundle:Employees',
                    'query_builder' => function(EntityRepository $er){
                        return $er->createQueryBuilder('e')
                            ->where('e.active = 1')
                            ->orderBy('e.lastname', 'ASC');
                    }
                ,
                    'multiple' => false,
                    'expanded' => false,
                    'placeholder' => '-',
                ))
                ->add('ui', 'entity', array(
                    'class' => 'ftiwebBundle:Employees',
                    'query_builder' => function(EntityRepository $er){
                        return $er->createQueryBuilder('e')
                            ->where('e.active = 1')
                            ->orderBy('e.lastname', 'ASC');
                    }
                ,
                    'multiple' => false,
                    'expanded' => false,
                    'placeholder' => '-',
                ))
                ->add('notes', 'textarea')
                ->add('submit', 'submit')
                ->add('SubmitAndAlert', 'submit')
                ->getForm();

    $shotForm->handleRequest($request);
    if($shotForm->isValid()) {
        $formData = $request->request->get('form');
        if ($formData['test']) {
            $shotObj->setTestevent($formData['test']);
        }
        $em->persist($shotObj);
        $em->flush();
    } 

返回的错误是: 执行“INSERT INTO 指标(baseline、testEvent、status、shotStart、shotEnd、c2p、notes、date、ui、assignedTo)VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' 带参数 ["foo", "foo", null, "2015-03-03 00:30:00", "2015-03-03 02:30:00", "foo", "test",空, 18, 21]:

如您所见,主键 (uniqueId) 不在要插入的列中,这让我相信它的映射 任何帮助将不胜感激

【问题讨论】:

  • 运行 app/console 学说:schema:create --dump-sql 和学说:schema:validate 以验证学说正在查看您的映射。您可能需要重建架构。你有不一致的拼写。仔细检查 setUniqueid() 是否正确。
  • 我已经运行了这些命令。为了检查学说是否正在查看我的映射,我确实将生成的值策略更改为不存在的东西,并且传播了一个错误。我已经确认 setUniquid() 和 getUniqueid() 有效。我有什么不正确的拼写?实体类是由学说自动生成的,因为我使用的是现有的 MySQL 数据库
  • 我说的不一致,不一定不正确。验证在表单发布后 $shotObj 是否仍然具有它的 id。也许表格中正在发生一些事情。顺便说一句,不需要将 id 作为隐藏值传递,实际上这有点危险,因为用户可以更改它。也只是尝试在没有表格的情况下发布实体。如果设置了 id,那么请简要介绍您的完整实体类(带有 getter 和 setter)。我会测试一下。
  • gist.github.com/b171e17685cfa704ff06.git 我照你说的做了,但无济于事。我还创建了另一个对象,设置了唯一 ID,并持久化并刷新到数据库,我收到了相同的结果。

标签: php symfony doctrine


【解决方案1】:

你应该玩@ORM\GeneratedValue(strategy="NONE"),你可以选择: AUTO, SEQUENCE, TABLE, IDENTITY, UUID, CUSTOM and NONE.

我用 AUTO - 告诉 Doctrine 选择使用的数据库平台首选的策略。对于MySQLSQLiteMsSQL,首选策略是IDENTITY,对于OraclePostgreSQL,首选策略是SEQUENCE。这种策略提供了完全的可移植性。

如果您使用 PHP 生成唯一标识,请使用下一个注释:

/**
 * @ORM\Column(type="guid")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="UUID")
 */

【讨论】:

  • 主键uniqueid是使用php的uniqid生成的值。所以它不应该是一个生成的值,因为我提供了 id。如果生成您自己的 id,文档说明不使用或不使用它。
  • 我用了,注解,还是没有。我在帖子下方的评论中发布了整个实体类的要点。我创建了一个单独的对象,设置了 uniqueid,并且我做了 echo getUniqueId() 以确保它被存储在 uniqueid 属性中,并持久化并刷新到 DB,但仍然是相同的结果。 uniqueid 列不在插入 DML 语句中。
  • 您能否从注释中删除 @ORM\Id 选项并对其进行测试,我认为当您指定对教义说的“Id”列时不要触摸它,让数据库处理它。
  • 也进行了测试。还是什么都没有。
【解决方案2】:

感谢所有帮助的人。答案最终是,在 orm.xml 文件中,生成的值永远不会改变,我在 xml 文档中手动删除了生成的值。在此之后,插入 DML 语句正常工作,我在我的数据库中看到了该行。 orm.xml 文件位于 Bundle/Resources/config/doctrine 目录中。

【讨论】:

  • 是的。您不能在同一个包中混合使用 orm 和注释。
猜你喜欢
  • 2010-09-24
  • 2023-01-18
  • 1970-01-01
  • 1970-01-01
  • 2019-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多