在 Symfony 中哪里初始化 Doctrine 的默认事务隔离级别?
Where to initialize Doctrine's default transaction isolation level in Symfony?
我想在我的 Symfony 应用程序中设置默认事务隔离级别 READ COMMITTED
,而不是 MySQL 的默认 REPEATABLE READ
。
基本上,我需要确保每当注入此 class 时,都会在 Doctrine\DBAL\Connection
上调用以下方法:
$connection->setTransactionIsolation(TransactionIsolationLevel::READ_COMMITTED);
在 Symfony 应用程序中执行此操作的正确位置是什么?我考虑过 Kernel
,但不确定如何在不必无条件实例化 Connection
.
的情况下执行此操作
相反,这应该只被称为 if 和 when Connection
被依赖注入容器实例化。
我认为没有可用于控制捆绑级别事务隔离的配置选项。
但可以修饰 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);
}
}
我想在我的 Symfony 应用程序中设置默认事务隔离级别 READ COMMITTED
,而不是 MySQL 的默认 REPEATABLE READ
。
基本上,我需要确保每当注入此 class 时,都会在 Doctrine\DBAL\Connection
上调用以下方法:
$connection->setTransactionIsolation(TransactionIsolationLevel::READ_COMMITTED);
在 Symfony 应用程序中执行此操作的正确位置是什么?我考虑过 Kernel
,但不确定如何在不必无条件实例化 Connection
.
相反,这应该只被称为 if 和 when Connection
被依赖注入容器实例化。
我认为没有可用于控制捆绑级别事务隔离的配置选项。
但可以修饰 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);
}
}