在 DBAL 和会话处理程序 Symfony2 之间共享数据库连接

pio*_*kkr 5 connection session pdo symfony doctrine-orm

我正在尝试在会话处理程序和学说 dbal 之间使用与我的数据库相同的连接:

配置文件

framework:
    session:
        handler_id:  session.handler.one_connection_pdo
Run Code Online (Sandbox Code Playgroud)

服务.yml

session.handler.one_connection_pdo:
    class:     AppBundle\Session\OneConnectionPdoHandler
    public:    false
    arguments:
        - "@database_connection"
        - []
Run Code Online (Sandbox Code Playgroud)

AppBundle/Session/OneConnectionPdoHandler.php

namespace AppBundle\Session;


use Doctrine\DBAL\Connection;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;

class OneConnectionPdoHandler extends PdoSessionHandler
{

    public function __construct($pdoOrDsn, array $options)
    {
        if ($pdoOrDsn instanceof Connection) {
            $pdoOrDsn = $pdoOrDsn->getWrappedConnection();
        }
        parent::__construct($pdoOrDsn, $options);
    }

}
Run Code Online (Sandbox Code Playgroud)

浏览应用程序时似乎一切正常,但我无法更新任何实体,因为出现错误:

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 Doctrine\DBAL\Connection->beginTransaction()
    in .../vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 373

at Doctrine\ORM\UnitOfWork->commit(null)
    in .../vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php line 356

at Doctrine\ORM\EntityManager->flush()
    in .../src/AppBundle/Controller/Admin/DistributorsController.php line 66

at AppBundle\Controller\Admin\DistributorsController->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 Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), '1')
    in .../vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php line 62

at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), '1', true)
    in .../vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php line 169

at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
    in .../web/app_dev.php line 31
Run Code Online (Sandbox Code Playgroud)

有没有办法在学说 dbal 和自定义 pdo 处理程序之间共享连接?

// 编辑

我终于在PdoSessionHandler课堂上找到了解决方案。

默认情况下,PDO 处理程序在读取和写入会话时使用事务。它首先启动事务read()并提交close()。在两者之间有一些数据库操作$em->persist($entity); $em->flush()产生了另一个产生错误的事务。

PdoSessionHandler课堂上我发现有一个lock_mode选项可以这样设置:

session.handler.one_connection_pdo:
    class:     AppBundle\Session\OneConnectionPdoHandler
    public:    false
    arguments:
        - "@database_connection"
        - { lock_mode: 1 }
Run Code Online (Sandbox Code Playgroud)

当 lock_mode 设置为 1 ( PdoSessionHandler::LOCK_ADVISORY) 时,PDO 处理程序将使用咨询锁而不是事务,并且不会再有事务错误。

小智 4

在 Symfony 3 中~

在(应用程序\配置\config.yml)中:

framework:
    session:
     handler_id: Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler
Run Code Online (Sandbox Code Playgroud)

在(应用程序\配置\services.yml)中:

 Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler:
        arguments:
            - !service { class: PDO, factory: 'database_connection:getWrappedConnection' }
            - {lock_mode: 1 }
Run Code Online (Sandbox Code Playgroud)