Doctrine 在 foreach 循环后只插入一条记录
Doctrine only inserts one record after foreach loop
我有一个简单的数组,其中包含一些需要插入到数据库中的值。在所有值中,只有最后一个值被实际插入。
当我将 flush();
放入循环中时,确实会插入记录。
当我在刷新之前(在 foreach 之外)转储实体管理器时,我确实看到了对所有值(实体)的引用。
不过,只插入了最后一条记录。它确实获得了 id #3,所以其他的似乎丢失了。
$values = [
"val1", "val2", "val3"
];
foreach ($values as $value) {
$i = new MyEntityClass();
$i->setVerified(false);
$i->setName($value);
$this->em->persist($i);
}
$this->em->flush();
更新:
我连接了一个事件监听器来预先和 post 刷新。
public function preFlush(PreFlushEventArgs $args) {
$em = $args->getEntityManager();
foreach ($em->getUnitOfWork()->getScheduledEntityInsertions() as $entity) {
dump($entity->getName());
}
}
public function postFlush(PostFlushEventArgs $args) {
dd($args->getEntityManager()->getUnitOfWork()->getScheduledEntityInsertions());
}
在 preFlush 中,所有值都被清楚地打印出来,postFlush dump 是空的。
更新 2:
我正在使用 uuid_binary_ordered_time 如下
/**
* @ORM\Id
* @ORM\Column(type="uuid_binary_ordered_time", unique=true)
* @GeneratedValue(strategy="CUSTOM")
* @CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidOrderedTimeGenerator")
* @Groups({"uuid"})
*/
protected $id;
使用 10.4.8-MariaDB
和 php v7.3.10
更新 3:
我仍在尝试解决这个问题,现在遇到了不同的情况,但我仍然 运行 遇到多个操作未执行的问题。这可能与数据库配置相关而不是 Doctrine?
案例:从tableA和tableB收集数据,插入数据到TableC,从tableA删除记录。
按照@Jakumi 的建议(或查看日志),我可以看到正在执行以下查询(剧透,table A 中的行已删除,但 [= 中没有新行43=] C):
"queries": {
"1": {
"sql": "SELECT t0.email AS email_1, t0.status AS status_2, t0.payment_provider_id AS payment_provider_id_3, t0.payment_method AS payment_method_4, t0.quantity AS quantity_5, t0.price_total AS price_total_6, t0.created_on AS created_on_7, t0.updated_on AS updated_on_8, t0.paid_on AS paid_on_9, t0.id AS id_10, t0.s_uuid AS s_uuid_11, t0.product_id AS product_id_12 FROM payment_pending t0 WHERE t0.payment_provider_id = ? LIMIT 1",
"params": [
"tr_S432rV6fhM"
],
"types": [
"string"
],
"executionMS": 0.0005559921264648438
},
"2": {
"sql": "SELECT t0.username AS username_1, t0.roles AS roles_2, t0.password AS password_3, t0.email AS email_4, t0.email_verified AS email_verified_5, t0.created_on AS created_on_6, t0.registration_method AS registration_method_7, t0.has_premium AS has_premium_8, t0.premium_until AS premium_until_9, t0.verified_mobile AS verified_mobile_10, t0.active AS active_11, t0.facebook_id AS facebook_id_12, t0.google_id AS google_id_13, t0.id AS id_14, t0.s_uuid AS s_uuid_15, t16.is_a AS is_a_17, t16.wants_a AS wants_a_18, t16.firstname AS firstname_19, t16.lastname AS lastname_20, t16.screen_name AS screen_name_21, t16.function_title AS function_title_22, t16.mobile_number AS mobile_number_23, t16.birthday AS birthday_24, t16.age AS age_25, t16.zipcode AS zipcode_26, t16.city AS city_27, t16.id AS id_28, t16.s_uuid AS s_uuid_29, t16.user_id AS user_id_30 FROM user t0 LEFT JOIN user_extra t16 ON t16.user_id = t0.id WHERE t0.email = ? LIMIT 1",
"params": [
"some@email.com"
],
"types": [
"string"
],
"executionMS": 0.0007460117340087891
},
"3": {
"sql": "\"START TRANSACTION\"",
"params": null,
"types": null,
"executionMS": 0.00010800361633300781
},
"4": {
"sql": "INSERT INTO user_payments (status, payment_provider_id, payment_method, quantity, price_total, created_on, updated_on, paid_on, id, s_uuid, user_id, product_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
"params": {
"1": "open",
"2": "tr_S432rV6fhM",
"3": "paypal",
"4": 1,
"5": "17.95",
"6": "2019-10-24T07:27:22+00:00",
"7": null,
"8": null,
"9": "9dd4af76-f630-11e9-90f2-024216133c1a",
"10": "9dd4af76-f630-11e9-90f2-024216133c1a",
"11": "c2abb28c-f62f-11e9-b71f-024216133c1a",
"12": "bce559e8-f5bc-11e9-85f8-024216133c1a"
},
"types": {
"1": "string",
"2": "string",
"3": "string",
"4": "integer",
"5": "decimal",
"6": "datetime",
"7": "datetime",
"8": "datetime",
"9": "uuid_binary_ordered_time",
"10": "uuid",
"11": "uuid_binary_ordered_time",
"12": "uuid_binary_ordered_time"
},
"executionMS": 0.0003437995910644531
},
"5": {
"sql": "DELETE FROM payment_pending WHERE id = ?",
"params": [
"b836c012-f62f-11e9-80b0-024216133c1a"
],
"types": [
"uuid_binary_ordered_time"
],
"executionMS": 0.0003409385681152344
},
"6": {
"sql": "\"COMMIT\"",
"params": null,
"types": null,
"executionMS": 0.09281802177429199
}
},
"enabled": true,
"start": 1571902427.83485,
"currentQuery": 6
你为什么不像这样在 persist 之后立即使用 flush:
$values = [
"val1", "val2", "val3"
];
foreach ($values as $value) {
$i = new MyEntityClass();
$i->setVerified(false);
$i->setName($value);
$this->em->persist($i);
$this->em->flush();
}
或更好:
public function save(MyEntityClass $myEntityClass): void
{
$this->em->persist($myEntityClass);
$this->em->flush();
}
在实体的存储库中,当您想单独保存相关实体时使用它
编辑 - 另一种尝试方法
$values = [
"val1", "val2", "val3"
];
$this->em->getConnection()->beginTransaction();
foreach ($values as $value) {
$i = new MyEntityClass();
$i->setVerified(false);
$i->setName($value);
$this->em->persist($i);
}
try {
$this->em->flush();
$this->em->getConnection()->commit();
} catch (Exception $e) {
$this->em->getConnection()->rollback();
$this->em->close();
throw $e;
}
还在 $id 的定义中添加行:
/**
* @var \Ramsey\Uuid\UuidInterface
*
* @ORM\Id
* @ORM\Column(type="uuid_binary_ordered_time", unique=true)
* @GeneratedValue(strategy="CUSTOM")
* @CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidOrderedTimeGenerator")
* @Groups({"uuid"})
*/
protected $id;
编辑 - 使用类型="uuid"
更新$id
的声明
/**
* Entity constructor.
*
* @param UuidInterface|null $uuid
*
* @throws \Exception
*/
public function __construct(UuidInterface $uuid = null)
{
if (null === $uuid) {
$uuid = Uuid::uuid4();
}
$this->id = $uuid;
[Other fields ...]
}
/**
* @var \Ramsey\Uuid\UuidInterface
*
* @ORM\Id
* @ORM\Column(type="uuid")
*/
protected $id;
/**
* @return UuidInterface|null
*/
public function getId(): ?UuidInterface
{
return $this->id;
}
这样做你应该排除它是 $id 来扰乱 Doctrine ...我们可以在别处调查
我仍然不确定是什么原因造成的,但我确实 'solve' 解决了这个问题。为此,我从我的开发环境中完全删除了 MariaDB、它的组件和数据库本身。
重新安装 MariaDB 后,运行 mysql_secure_installation、重新创建数据库和 运行 迁移,一切都按预期工作。
$this->em->flush();
现在在 foreach 之外插入所有记录,我的第二个问题案例也是如此。
我有一个简单的数组,其中包含一些需要插入到数据库中的值。在所有值中,只有最后一个值被实际插入。
当我将 flush();
放入循环中时,确实会插入记录。
当我在刷新之前(在 foreach 之外)转储实体管理器时,我确实看到了对所有值(实体)的引用。
不过,只插入了最后一条记录。它确实获得了 id #3,所以其他的似乎丢失了。
$values = [
"val1", "val2", "val3"
];
foreach ($values as $value) {
$i = new MyEntityClass();
$i->setVerified(false);
$i->setName($value);
$this->em->persist($i);
}
$this->em->flush();
更新: 我连接了一个事件监听器来预先和 post 刷新。
public function preFlush(PreFlushEventArgs $args) {
$em = $args->getEntityManager();
foreach ($em->getUnitOfWork()->getScheduledEntityInsertions() as $entity) {
dump($entity->getName());
}
}
public function postFlush(PostFlushEventArgs $args) {
dd($args->getEntityManager()->getUnitOfWork()->getScheduledEntityInsertions());
}
在 preFlush 中,所有值都被清楚地打印出来,postFlush dump 是空的。
更新 2: 我正在使用 uuid_binary_ordered_time 如下
/**
* @ORM\Id
* @ORM\Column(type="uuid_binary_ordered_time", unique=true)
* @GeneratedValue(strategy="CUSTOM")
* @CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidOrderedTimeGenerator")
* @Groups({"uuid"})
*/
protected $id;
使用 10.4.8-MariaDB
和 php v7.3.10
更新 3: 我仍在尝试解决这个问题,现在遇到了不同的情况,但我仍然 运行 遇到多个操作未执行的问题。这可能与数据库配置相关而不是 Doctrine?
案例:从tableA和tableB收集数据,插入数据到TableC,从tableA删除记录。
按照@Jakumi 的建议(或查看日志),我可以看到正在执行以下查询(剧透,table A 中的行已删除,但 [= 中没有新行43=] C):
"queries": {
"1": {
"sql": "SELECT t0.email AS email_1, t0.status AS status_2, t0.payment_provider_id AS payment_provider_id_3, t0.payment_method AS payment_method_4, t0.quantity AS quantity_5, t0.price_total AS price_total_6, t0.created_on AS created_on_7, t0.updated_on AS updated_on_8, t0.paid_on AS paid_on_9, t0.id AS id_10, t0.s_uuid AS s_uuid_11, t0.product_id AS product_id_12 FROM payment_pending t0 WHERE t0.payment_provider_id = ? LIMIT 1",
"params": [
"tr_S432rV6fhM"
],
"types": [
"string"
],
"executionMS": 0.0005559921264648438
},
"2": {
"sql": "SELECT t0.username AS username_1, t0.roles AS roles_2, t0.password AS password_3, t0.email AS email_4, t0.email_verified AS email_verified_5, t0.created_on AS created_on_6, t0.registration_method AS registration_method_7, t0.has_premium AS has_premium_8, t0.premium_until AS premium_until_9, t0.verified_mobile AS verified_mobile_10, t0.active AS active_11, t0.facebook_id AS facebook_id_12, t0.google_id AS google_id_13, t0.id AS id_14, t0.s_uuid AS s_uuid_15, t16.is_a AS is_a_17, t16.wants_a AS wants_a_18, t16.firstname AS firstname_19, t16.lastname AS lastname_20, t16.screen_name AS screen_name_21, t16.function_title AS function_title_22, t16.mobile_number AS mobile_number_23, t16.birthday AS birthday_24, t16.age AS age_25, t16.zipcode AS zipcode_26, t16.city AS city_27, t16.id AS id_28, t16.s_uuid AS s_uuid_29, t16.user_id AS user_id_30 FROM user t0 LEFT JOIN user_extra t16 ON t16.user_id = t0.id WHERE t0.email = ? LIMIT 1",
"params": [
"some@email.com"
],
"types": [
"string"
],
"executionMS": 0.0007460117340087891
},
"3": {
"sql": "\"START TRANSACTION\"",
"params": null,
"types": null,
"executionMS": 0.00010800361633300781
},
"4": {
"sql": "INSERT INTO user_payments (status, payment_provider_id, payment_method, quantity, price_total, created_on, updated_on, paid_on, id, s_uuid, user_id, product_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
"params": {
"1": "open",
"2": "tr_S432rV6fhM",
"3": "paypal",
"4": 1,
"5": "17.95",
"6": "2019-10-24T07:27:22+00:00",
"7": null,
"8": null,
"9": "9dd4af76-f630-11e9-90f2-024216133c1a",
"10": "9dd4af76-f630-11e9-90f2-024216133c1a",
"11": "c2abb28c-f62f-11e9-b71f-024216133c1a",
"12": "bce559e8-f5bc-11e9-85f8-024216133c1a"
},
"types": {
"1": "string",
"2": "string",
"3": "string",
"4": "integer",
"5": "decimal",
"6": "datetime",
"7": "datetime",
"8": "datetime",
"9": "uuid_binary_ordered_time",
"10": "uuid",
"11": "uuid_binary_ordered_time",
"12": "uuid_binary_ordered_time"
},
"executionMS": 0.0003437995910644531
},
"5": {
"sql": "DELETE FROM payment_pending WHERE id = ?",
"params": [
"b836c012-f62f-11e9-80b0-024216133c1a"
],
"types": [
"uuid_binary_ordered_time"
],
"executionMS": 0.0003409385681152344
},
"6": {
"sql": "\"COMMIT\"",
"params": null,
"types": null,
"executionMS": 0.09281802177429199
}
},
"enabled": true,
"start": 1571902427.83485,
"currentQuery": 6
你为什么不像这样在 persist 之后立即使用 flush:
$values = [
"val1", "val2", "val3"
];
foreach ($values as $value) {
$i = new MyEntityClass();
$i->setVerified(false);
$i->setName($value);
$this->em->persist($i);
$this->em->flush();
}
或更好:
public function save(MyEntityClass $myEntityClass): void
{
$this->em->persist($myEntityClass);
$this->em->flush();
}
在实体的存储库中,当您想单独保存相关实体时使用它
编辑 - 另一种尝试方法
$values = [
"val1", "val2", "val3"
];
$this->em->getConnection()->beginTransaction();
foreach ($values as $value) {
$i = new MyEntityClass();
$i->setVerified(false);
$i->setName($value);
$this->em->persist($i);
}
try {
$this->em->flush();
$this->em->getConnection()->commit();
} catch (Exception $e) {
$this->em->getConnection()->rollback();
$this->em->close();
throw $e;
}
还在 $id 的定义中添加行:
/**
* @var \Ramsey\Uuid\UuidInterface
*
* @ORM\Id
* @ORM\Column(type="uuid_binary_ordered_time", unique=true)
* @GeneratedValue(strategy="CUSTOM")
* @CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidOrderedTimeGenerator")
* @Groups({"uuid"})
*/
protected $id;
编辑 - 使用类型="uuid"
更新$id
的声明/**
* Entity constructor.
*
* @param UuidInterface|null $uuid
*
* @throws \Exception
*/
public function __construct(UuidInterface $uuid = null)
{
if (null === $uuid) {
$uuid = Uuid::uuid4();
}
$this->id = $uuid;
[Other fields ...]
}
/**
* @var \Ramsey\Uuid\UuidInterface
*
* @ORM\Id
* @ORM\Column(type="uuid")
*/
protected $id;
/**
* @return UuidInterface|null
*/
public function getId(): ?UuidInterface
{
return $this->id;
}
这样做你应该排除它是 $id 来扰乱 Doctrine ...我们可以在别处调查
我仍然不确定是什么原因造成的,但我确实 'solve' 解决了这个问题。为此,我从我的开发环境中完全删除了 MariaDB、它的组件和数据库本身。
重新安装 MariaDB 后,运行 mysql_secure_installation、重新创建数据库和 运行 迁移,一切都按预期工作。
$this->em->flush();
现在在 foreach 之外插入所有记录,我的第二个问题案例也是如此。