在 PHP8.1 上使用 Doctrine v2.12.2 和 MySQL5.7.38 数据库,尝试使用下面定义的
wrapInTransaction
函数内部的 setValue
方法来持久化数据实体;我的理解是,成功完成 wrapInTransaction
方法后,实体应该存在于数据库中;在调试和单步执行时,AccountSettingModelImpl
实体对象在字段中填充了所有正确的数据,但从未在数据库中看到该条目。该方法被多次调用以设置数据;但我的假设是,因为它没有被存储,所以当调用 fetchSettingByKey
时,会返回一个错误,然后陷入 Doctrine 尝试再次创建实体并抛出“重复条目”异常的陷阱。
奇怪的是,一些值存储在数据库中,但似乎 php 请求必须成功完成才能发生这种情况。是否有必须启用才能使
wrapInTransaction
立即持续存在的设置?
/**
* Class SettingModel
* @package kor\classes\models
* @Entity @Table(name="korAccountSettings")
*/
class AccountSettingModelImpl extends AbstractBaseModel implements AccountSettingModel
{
/**
* @Id
* @ManyToOne(targetEntity="AccountModelImpl")
* @JoinColumn(name="asAccountId", referencedColumnName="aId")
* @var AccountModelImpl
*/
private AccountModel $account;
/**
* @Id
* @Column(name="asKey", type="text")
* @var string
*/
private string $key;
/**
* @Column(name="asVal", type="text", nullable=true)
* @var mixed
*/
private ?string $val;
/**
* @Column(name="asUpdated", type="datetime_immutable")
* @var DateTime
*/
private DateTimeInterface $updated;
}
public function setValue(string $sKey, $sVal)
{
Application::getEntityManager()->wrapInTransaction(function (EntityManager $entityManager)
use ($sKey, $sVal) {
$accountModel = $this->getAccountModel();
try {
$settingModel = AccountSettingHelper::fetchSettingByKey($sKey, $accountModel);
$settingModel->setVal($sVal);
if(is_null($sVal) && $entityManager->contains($settingModel))
$entityManager->remove($settingModel);
} catch (SettingNotFoundException $e) {
$settingModel = Application::newEntity(AccountSettingModel::class);
$settingModel->setAccount($accountModel);
$settingModel->setKey($sKey);
$settingModel->setVal($sVal);
$entityManager->persist($settingModel);
}
});
return $sVal;
}
An exception occurred while executing a query: Duplicate entry '1-rl.enabled' for key 'PRIMARY'
#0 OR\vendor\doctrine\dbal\src\Connection.php(1814): Doctrine\DBAL\Driver\API\MySQL\ExceptionConverter->convert()
#1 OR\vendor\doctrine\dbal\src\Connection.php(1749): Doctrine\DBAL\Connection->handleDriverException()
#2 OR\vendor\doctrine\dbal\src\Statement.php(184): Doctrine\DBAL\Connection->convertExceptionDuringQuery()
#3 OR\vendor\doctrine\dbal\src\Statement.php(221): Doctrine\DBAL\Statement->execute()
#4 OR\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\Entity\BasicEntityPersister.php(278): Doctrine\DBAL\Statement->executeStatement()
#5 OR\vendor\doctrine\orm\lib\Doctrine\ORM\UnitOfWork.php(1129): Doctrine\ORM\Persisters\Entity\BasicEntityPersister->executeInserts()
#6 OR\vendor\doctrine\orm\lib\Doctrine\ORM\UnitOfWork.php(426): Doctrine\ORM\UnitOfWork->executeInserts()
#7 OR\vendor\doctrine\orm\lib\Doctrine\ORM\EntityManager.php(398): Doctrine\ORM\UnitOfWork->commit()
#8 OR\vendor\doctrine\orm\lib\Doctrine\ORM\EntityManager.php(269): Doctrine\ORM\EntityManager->flush()
您需要调用
$entityManager->flush()
来触发对数据库的提交。
这可能发生在代码中的其他地方,从而触发您描述的行为。