英文:
Shopware 6 database transactions for repositories?
问题
In Shopware 6,我们已经实现了一个可以与多个数据库表一起工作的优惠券插件。为了避免竞态条件或不一致的数据,最好使用数据库事务。
在与多个实体仓库一起工作时,如何执行此操作?
在SQL级别上,应该类似于以下内容:
begin;
SELECT code FROM voucher_pool;
INSERT INTO voucher_code (code, active, value, valid_until) VALUES ('ABCDEF', 1, 20, '2025-01-01');
INSERT INTO voucher_code_transaction (code_id, value) VALUES (X'...', +20);
UPDATE voucher_pool SET redeemed=1 WHERE code='ABCDEF';
commit;
在Shopware级别上,voucher_code
和 voucher_code_transaction
可以作为一个请求使用。但是我们不确定如何将 voucher_pool
表添加到同一个事务中。应该如下所示:
// 开始事务
try {
$availableCode = $this->voucherPoolRepository->search($criteria, $context)->first();
$this->voucherCodeRepository->upsert([
[
'code' => $availableCode->getCode(),
'active' => true,
'value' => 20,
'valid_until' => '2025-01-01',
'transactions' => [
[
'value' => 20,
],
],
],
], $context);
$this->voucherPoolRepository->update([
[
'id' => $availableCode->getId(),
'redeemed' => true,
],
], $context);
// 提交事务
} catch (Throwable) {
// 回滚事务
}
在其他购物系统中,比如Magento,有一个事务对象,您可以将对象添加到其中,以触发一次联合保存。在Shopware 6中是否有类似的东西?还是只能使用Doctrine的Connection对象来执行事务?
例如:
/** @var \Doctrine\DBAL\Connection $connection */
$connection->beginTransaction();
$this->voucherCodeRepository->upsert(...);
$this->voucherPoolRepository->update(...);
$connection->commit();
英文:
In Shopware 6 we have implemented a voucher plugin that works with several database tables. To avoid race conditions or inconsistent data, it would make sense to use database transactions.
How can we do this when working with multiple entity repositories?
At SQL level it should look something like this:
begin;
SELECT code FROM voucher_pool;
INSERT INTO voucher_code (code, active, value, valid_until) VALUES ('ABCDEF', 1, 20, '2025-01-01');
INSERT INTO voucher_code_transaction (code_id, value) VALUES (X'...', +20);
UPDATE voucher_pool SET redeemed=1 WHERE code='ABCDEF';
commit;
At Shopware level, voucher_code
and voucher_code_transaction
can be used as one request. But we are not sure how to add the voucher_pool
table to the same transaction. It should look like this:
// begin transaction
try {
$availableCode = $this->voucherPoolRepository->search($criteria, $context)->first();
$this->voucherCodeRepository->upsert([
[
'code' => $availableCode->getCode(),
'active' => true,
'value' => 20,
'valid_until' => '2025-01-01',
'transactions' => [
[
'value' => 20,
],
],
],
], $context);
$this->voucherPoolRepository->update([
[
'id' => $availableCode->getId(),
'redeemed' => true,
],
], $context);
// commit
} catch (Throwable) {
// rollback
}
In other shop systems, such as Magento, there is a transaction object to which you can add objects to trigger a combined save at once. Is there something like this in Shopware 6? Or are transactions only possible with the Connection object from Doctrine?
e.g.
/** @var \Doctrine\DBAL\Connection $connection */
$connection->beginTransaction();
$this->voucherCodeRepository->upsert(...);
$this->voucherPoolRepository->update(...);
$connection->commit();
答案1
得分: 1
你可以使用 SyncService
来合并不同实体的多个写操作。
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\Api\Sync\SyncBehavior;
use Shopware\Core\Framework\Api\Sync\SyncOperation;
use Shopware\Core\Framework\Api\Sync\SyncService;
$this->container->get(SyncService::class)->sync([
new SyncOperation(
'write',
VoucherCodeDefinition::ENTITY_NAME,
SyncOperation::ACTION_UPSERT,
$codePayload
),
new SyncOperation(
'write',
VoucherPoolDefinition::ENTITY_NAME,
SyncOperation::ACTION_UPSERT,
$poolPayload
),
], Context::createDefaultContext(), new SyncBehavior());
英文:
You can combine multiple write operations of different entities using the SyncService
.
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\Api\Sync\SyncBehavior;
use Shopware\Core\Framework\Api\Sync\SyncOperation;
use Shopware\Core\Framework\Api\Sync\SyncService;
$this->container->get(SyncService::class)->sync([
new SyncOperation(
'write',
VoucherCodeDefinition::ENTITY_NAME,
SyncOperation::ACTION_UPSERT,
$codePayload
),
new SyncOperation(
'write',
VoucherPoolDefinition::ENTITY_NAME,
SyncOperation::ACTION_UPSERT,
$poolPayload
),
], Context::createDefaultContext(), new SyncBehavior());
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论