Где инициализировать Doctrine уровень изоляции транзакции по умолчанию в Symfony? - PullRequest
1 голос
/ 28 января 2020

Я бы хотел установить уровень изоляции транзакции по умолчанию READ COMMITTED вместо MySQL по умолчанию REPEATABLE READ во всем моем приложении Symfony.

По сути, мне нужно убедиться, что что следующий метод вызывается на Doctrine\DBAL\Connection всякий раз, когда вводится этот класс:

$connection->setTransactionIsolation(TransactionIsolationLevel::READ_COMMITTED);

Какое место для этого нужно сделать в приложении Symfony? Я думаю о Kernel, но не уверен, как это сделать без необходимости безоговорочно создавать экземпляр Connection.

Вместо этого это следует называть , если и когда , экземпляр Connection создается контейнером ввода зависимостей.

1 Ответ

2 голосов
/ 28 января 2020

Я не верю, что есть опция конфигурации, доступная для контроля изоляции транзакций на уровне пакета.

Но можно украсить Doctrine\Bundle\DoctrineBundle\ConnectionFactory, а на createConnection() установить уровень изоляции транзакции перед возвратом созданное соединение.

# services.yaml
    App\YourOwnConnectionFactory:
        decorates: '@doctrine.dbal.connection_factory'
class YourOwnConnectionFactory
{
    private ConnectionFactory $decorated;

    public function __construct(ConnectionFactory $decorated) {
        $this->decorated = $decorated;
    }

    public function createConnection(array $params, Configuration $config = null, EventManager $eventManager = null, array $mappingTypes = []) {
        $connection = $this->decorated->createConnection($params, $config, $eventManager, $mappingTypes);
        $connection->setTransactionIsolation(TransactionIsolationLevel::READ_COMMITTED);
        return $connection;
    }
}

Вы также можете изменить определение doctrine.dbal.connection, чтобы добавить вызов к setTransactionIsolation() в рамках прохода компилятора. Не уверен, что так будет лучше. Я полагаю, что оба метода имеют свои недостатки, которые вам необходимо оценить в соответствии с вашими обстоятельствами:

class FooPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
            $container
                ->getDefinition('doctrine.dbal.default_connection')
                ->addMethodCall(
                    'setTransactionIsolation',
                    [TransactionIsolationLevel::READ_COMMITTED]
                );

    }
}

Еще один вариант - добавить функцию-конфигуратор в проход компилятора:

class FooPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $container
            ->getDefinition('doctrine.dbal.default_connection')
            ->setConfigurator([self::class, 'setTransactionIsolationLevel']);
    }

    public static function setTransactionIsolationLevel(Connection $connection) : void
    {
        $connection->setTransactionIsolation(TransactionIsolationLevel::READ_COMMITTED);
    }
}
...