我正在尝试在会话处理程序和 doctrine dbal 之间使用相同的数据库连接:
配置.yml
framework:
session:
handler_id: session.handler.one_connection_pdo
服务.yml
session.handler.one_connection_pdo:
class: AppBundleSessionOneConnectionPdoHandler
public: false
arguments:
- "@database_connection"
- []
AppBundle/Session/OneConnectionPdoHandler.php
namespace AppBundleSession;
use DoctrineDBALConnection;
use SymfonyComponentHttpFoundationSessionStorageHandlerPdoSessionHandler;
class OneConnectionPdoHandler extends PdoSessionHandler
{
public function __construct($pdoOrDsn, array $options)
{
if ($pdoOrDsn instanceof Connection) {
$pdoOrDsn = $pdoOrDsn->getWrappedConnection();
}
parent::__construct($pdoOrDsn, $options);
}
}
浏览应用程序时一切似乎都正常,但我无法更新任何实体,因为我收到错误:
PDOException: There is already an active transaction
at n/a
in .../vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php line 1176
at PDO->beginTransaction()
in .../vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php line 1176
at DoctrineDBALConnection->beginTransaction()
in .../vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 373
at DoctrineORMUnitOfWork->commit(null)
in .../vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php line 356
at DoctrineORMEntityManager->flush()
in .../src/AppBundle/Controller/Admin/DistributorsController.php line 66
at AppBundleControllerAdminDistributorsController->editAction(object(Distributor), object(Request))
in line
at call_user_func_array(array(object(DistributorsController), 'editAction'), array(object(Distributor), object(Request)))
in .../vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php line 139
at SymfonyComponentHttpKernelHttpKernel->handleRaw(object(Request), '1')
in .../vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php line 62
at SymfonyComponentHttpKernelHttpKernel->handle(object(Request), '1', true)
in .../vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php line 169
at SymfonyComponentHttpKernelKernel->handle(object(Request))
in .../web/app_dev.php line 31
有没有办法在学说 dbal 和自定义 pdo 处理程序之间共享连接?
//编辑
我终于在课堂上找到了解决方案PdoSessionHandler
。
默认情况下,PDO处理程序在读取和写入会话时使用事务。它在第一个read()
开始事务,并在close()
提交。在这两者之间有一些数据库操作$em->persist($entity); $em->flush()
产生了另一个产生错误的事务。
在类PdoSessionHandler
我发现有一个lock_mode
选项可以像这样设置:
session.handler.one_connection_pdo:
class: AppBundleSessionOneConnectionPdoHandler
public: false
arguments:
- "@database_connection"
- { lock_mode: 1 }
当lock_mode设置为 1 (PdoSessionHandler::LOCK_ADVISORY
) 时,PDO 处理程序将使用咨询锁而不是事务,并且不会再有事务错误。
In Symfony 3~
在 (app\config\config.yml) 中:
framework:
session:
handler_id: SymfonyComponentHttpFoundationSessionStorageHandlerPdoSessionHandler
在 (app\config\services.yml) 中:
SymfonyComponentHttpFoundationSessionStorageHandlerPdoSessionHandler:
arguments:
- !service { class: PDO, factory: 'database_connection:getWrappedConnection' }
- {lock_mode: 1 }