Doctrine migrations执行插入操作后如何立即获取新插入数据的值
问题根本原因
Doctrine迁移的addSql()方法不会立刻执行传入的SQL语句,而是会将SQL加入待执行队列,默认等待整个up()方法执行完成无报错后,才会批量执行队列中的所有SQL。同时迁移默认开启全局事务,若执行过程中抛出错误,整个事务会直接回滚,所以你遇到了对应的现象:
- 执行查询时插入语句还未实际执行,查询结果为空,触发
Undefined offset: 0报错 - 报错触发事务回滚,最终数据库内没有插入数据
- 注释掉查询代码后,
up()方法无报错正常结束,队列中的插入语句被执行,数据成功写入
解决方案
你可以通过以下几种方式实现插入后立刻获取数据:
- 方案1:直接用数据库连接同步执行插入,不走addSql队列
直接调用迁移类内置的数据库连接执行插入语句,执行后立刻生效,后续可以正常查询:// 直接执行插入,同步生效 $this->connection->executeStatement("INSERT INTO `mytable` (`name`) VALUES ('myvalue')"); $res = $this->em->createQueryBuilder() ->select('a') ->from(MyEntityClass::class, 'a') ->where("a.name = :name") ->setParameter('name', 'myvalue') ->getQuery() ->getResult(); $id = $res[0]->getId(); // 后续使用$id的逻辑 - 方案2:通过EntityManager持久化实体,直接获取ID
如果你操作的实体有对应的ORM映射,直接通过实体操作更简便,flush后可以直接拿到生成的ID,不需要额外查询:$entity = new MyEntityClass(); $entity->setName('myvalue'); $this->em->persist($entity); $this->em->flush(); $id = $entity->getId(); // 后续使用$id的逻辑 - 方案3:拆分迁移步骤(适合批量操作场景)
如果你确实需要使用addSql()管理批量SQL,可以将插入和后续依赖操作拆分到两个独立的迁移类中,前一个迁移执行插入,后一个迁移执行查询和后续操作,保证前序操作已经完全生效。
注意:迁移过程中尽量避免混用
addSql()队列操作和实时数据库操作,二者执行时机不一致很容易触发事务、数据可见性问题。
内容的提问来源于stack exchange,提问作者user3174311
相关产品推荐
相关产品推荐

