使用错误连接的 Doctrine 实体管理器
Doctrine entity manager using wrong connection
根据 Symfony docs,可以配置多个实体管理器,方法是在 config/packages/doctrine.yaml
中列出它们,然后在控制器中选择一个特定的实体管理器,如下所示:$this->getDoctrine()->getManager('customer');
.
我设置了我的 config/packages/doctrine.yaml
:
doctrine:
dbal:
default_connection: default
connections:
default:
# configure these for your database server
url: '%env(DATABASE_URL)%'
driver: 'pdo_mysql'
server_version: '8.0'
charset: utf8mb4
meter:
# configure these for your database server
url: '%env(DATABASE_METER_URL)%'
driver: 'pdo_mysql'
server_version: '8.0'
charset: utf8mb4
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
naming_strategy: doctrine.orm.naming_strategy.underscore
mappings:
App:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
meter:
connection: meter
naming_strategy: doctrine.orm.naming_strategy.underscore
mappings:
App:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
然后尝试使用
进行查询
$meterEntityManager = $this->getDoctrine()->getManager('meter');
$meter = $meterEntityManager->getRepository(Entity\Meter::class)->find($meterId);
但是,$meterEntityManager->getRepository(Entity\Meter::class)->find($meterId)
的结果是来自名为 default
的数据库连接的一行,而不是名为 meter
的行——就好像代码是
$entityManager = $this->getDoctrine()->getManager('default');
$meter = $entityManager->getRepository(Entity\Meter::class)->find($meterId);
当我检查与 $meterEntityManager->getConnection()->getParams()
的连接时,它正确地列出了 meter
连接而不是 default
连接的参数,因此我可以从 meter
通过直接在连接对象上执行查询来连接数据库:
$meterEntityManager = $this->getDoctrine()->getManager('meter');
$stmt = $meterEntityManager->getConnection()->prepare('SELECT * FROM meter WHERE id = :id');
$stmt->execute(['id' => $meterId]);
$meter = $stmt->fetch();
但最终我想通过 getRepository(Entity\Meter::class)
提供的方法获取行,因此返回的数据会自动混合到学说实体中。 $meterEntityManager->getRepository(Entity\Meter::class)
和 $meterEntityManager->getConnection()
使用的连接似乎不一致。为什么是这样?这是否与使用不同连接但共享相同实体映射的实体管理器有关?
这里的基本问题是 ServiceEntityRepository class 遍历实体管理器列表并使用支持给定实体的第一个。这很好,除非您碰巧拥有多个实体管理器支持的实体。解决方案是 "old school" 并从 EntityRepository class 扩展,而不是基本上是容器感知的 ServiceEntityRepository。
use Doctrine\ORM\EntityRepository;
class MeterRepository extends EntityRepository
{
// Note: Do not override the constructor here
您还必须将 App\Repository 目录添加到 services.yaml 中的排除目录列表中。
ServiceEntityRepository 的原因是允许 Symfony 容器自动装配存储库并将它们直接注入到其他服务中。如果他们愿意,它还允许开发人员将额外的依赖项注入存储库。
根据 Symfony docs,可以配置多个实体管理器,方法是在 config/packages/doctrine.yaml
中列出它们,然后在控制器中选择一个特定的实体管理器,如下所示:$this->getDoctrine()->getManager('customer');
.
我设置了我的 config/packages/doctrine.yaml
:
doctrine:
dbal:
default_connection: default
connections:
default:
# configure these for your database server
url: '%env(DATABASE_URL)%'
driver: 'pdo_mysql'
server_version: '8.0'
charset: utf8mb4
meter:
# configure these for your database server
url: '%env(DATABASE_METER_URL)%'
driver: 'pdo_mysql'
server_version: '8.0'
charset: utf8mb4
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
naming_strategy: doctrine.orm.naming_strategy.underscore
mappings:
App:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
meter:
connection: meter
naming_strategy: doctrine.orm.naming_strategy.underscore
mappings:
App:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
然后尝试使用
进行查询$meterEntityManager = $this->getDoctrine()->getManager('meter');
$meter = $meterEntityManager->getRepository(Entity\Meter::class)->find($meterId);
但是,$meterEntityManager->getRepository(Entity\Meter::class)->find($meterId)
的结果是来自名为 default
的数据库连接的一行,而不是名为 meter
的行——就好像代码是
$entityManager = $this->getDoctrine()->getManager('default');
$meter = $entityManager->getRepository(Entity\Meter::class)->find($meterId);
当我检查与 $meterEntityManager->getConnection()->getParams()
的连接时,它正确地列出了 meter
连接而不是 default
连接的参数,因此我可以从 meter
通过直接在连接对象上执行查询来连接数据库:
$meterEntityManager = $this->getDoctrine()->getManager('meter');
$stmt = $meterEntityManager->getConnection()->prepare('SELECT * FROM meter WHERE id = :id');
$stmt->execute(['id' => $meterId]);
$meter = $stmt->fetch();
但最终我想通过 getRepository(Entity\Meter::class)
提供的方法获取行,因此返回的数据会自动混合到学说实体中。 $meterEntityManager->getRepository(Entity\Meter::class)
和 $meterEntityManager->getConnection()
使用的连接似乎不一致。为什么是这样?这是否与使用不同连接但共享相同实体映射的实体管理器有关?
这里的基本问题是 ServiceEntityRepository class 遍历实体管理器列表并使用支持给定实体的第一个。这很好,除非您碰巧拥有多个实体管理器支持的实体。解决方案是 "old school" 并从 EntityRepository class 扩展,而不是基本上是容器感知的 ServiceEntityRepository。
use Doctrine\ORM\EntityRepository;
class MeterRepository extends EntityRepository
{
// Note: Do not override the constructor here
您还必须将 App\Repository 目录添加到 services.yaml 中的排除目录列表中。
ServiceEntityRepository 的原因是允许 Symfony 容器自动装配存储库并将它们直接注入到其他服务中。如果他们愿意,它还允许开发人员将额外的依赖项注入存储库。