Соединение с базой данных для чтения реплики никогда не использовалось, возвращается к значениям по умолчанию

Я слежу за документацией здесь https://symfony.com/doc/current/reference/configuration/doctrine.html о настройке альтернативных подключений к базе данных с целью репликации чтения. Для справки я использую AWS Aurora PostgreSQL с конечными точками для основного и только для чтения.

Я установил это для своего doctrine.yaml

doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                url: '%env(resolve:DATABASE_URL)%'
            read:
                url: '%env(resolve:READ_URL)%'
    orm:
        default_entity_manager: default
        entity_managers:
            default:
                connection: default
                naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
                auto_mapping: true
                dql:
                    datetime_functions:
                        date_trunc: App\DoctrineExtensions\DateTrunc
                mappings:
                    App:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity'
                        prefix: 'App\Entity'
                        alias: App
            read:
                connection: read
                naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
                auto_mapping: false
                dql:
                    datetime_functions:
                        date_trunc: App\DoctrineExtensions\DateTrunc
                mappings:
                    App:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity'
                        prefix: 'App\Entity'
                        alias: App
        auto_generate_proxy_classes: true

И вызывая orm только для чтения как:

$user = $this->getDoctrine()->getRepository(User::class, 'read')->findOneBy(['email' => $payload['email']]);

Например.

Если я назову это, он все равно попадет в базу данных по умолчанию. Если я неправильно назову его, Symfony выдает исключение, как и ожидалось, поэтому я могу подтвердить, что конфигурация подобрана и загружается правильно.

Как моя конфигурация или вызов неверны, что он все еще запрашивает у defaultподключение к базе данных или есть лучший способ определить реплики чтения для подключения к данным? Я не нашел для него никакой текущей документации.

1 ответ

Согласно этому:

Один объект может управляться более чем одним менеджером объекта. Однако это приводит к неожиданному поведению при расширении из ServiceEntityRepository в вашем настраиваемом репозитории. ServiceEntityRepository всегда использует настроенный диспетчер сущностей для этой сущности. Чтобы исправить эту ситуацию, вместо этого расширьте EntityRepository и больше не полагайтесь на автоматическое подключение:

Поэтому вы должны убедиться, что ваш репозиторий расширяется EntityRepository вместо ServiceEntityRepository.

Тогда вы должны теперь всегда получать этот репозиторий, используя ManagerRegistry::getRepository().

Так что в основном это будет работать, так как $this->getDoctrine() вернуть экземпляр ManagerRegistry.

$user = $this->getDoctrine()->getRepository(User::class, 'read')->findOneBy(['email' => $payload['email']]);

Обратной стороной является то, что вы не сможете использовать автоподключение для самого репозитория.

Таким образом, это не сработает, если вы не передадите этот репозиторий вручную.

public function __construct(UserRepository $userRepository)
{
    $this->userRepository = $userRepository;
}
Другие вопросы по тегам