在特定实体的存储库中使用不同的实体管理器 objects

Use different Entity Manager in the Repository of specific Entity objects

我已按照手册中的 How to Work with multiple Entity Managers and Connections 章节在我的应用程序中配置和使用不同的实体管理器,因为一些实体存储在不同的数据库服务器中。

在控制器中,我需要使用 2 个实体管理器:默认用于客户、号码和付款,另一个用于合同。

但是,当我为合同调用存储库自定义方法 fetchMainByClient() 时,它应该使用 "custom" 实体管理器而不是默认的实体管理器,我收到一个数据库错误,这表明正在使用存储库中的默认实体管理器。

An exception occurred while executing 'SELECT ... FROM CONTRACTS c0_ WHERE c0_.ClientId = ? AND c0_.Type = 'Main'' with params [35736]:

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'DEFAULTDB.CONTRACTS' doesn't exist

如果我尝试使用已经可用的存储库方法,如 findOneBy()

,则会出现同样的错误

我做错了什么?

这是 Controller 的、Repository 的代码和 Contract 实体 header,以及 doctrine 配置。不是正品,但是很像。

控制器

public function index(Request $request, PaymentsRepository $payments_repository): Response
{
    $payments = $payments_repository->findLatest($page, $this->getUser()->getId());

    $form = $this->createForm(CreatePaymentType::class);

    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $payment = $form->getData();

        $em = $this->get('doctrine.orm.default_entity_manager');
        $cr = $em->getRepository(Numbers::class);
        $number = $tr->findOneByNumber($payment->getNumber());

        if (!$number) {
            $this->addFlash('error', 'numbers.missing_number');
        } else {
            $client = $number->getClients();
            if (!$client) {
                $this->addFlash('error', 'clients.missing_client');
            } else {
                //$em_custom = $this->get('doctrine.orm.custom_entity_manager');
                $em_custom = $this->getDoctrine()->getManager('custom');
                $contracts_repo = $em_custom->getRepository(Contracts::class);
                //dump($em, $em_custom, $contracts_repo);

                $contract = $contracts_repo->fetchMainByClient($client->getId());
                $contracts_repo->increaseCredit($payment->getValue());

                $payment->setDate(...);
                $payment->setClientId($client->getId());
                ...
                $em->persist($payment);
                $em->flush();

                $this->addFlash('success', 'flash.success_insert');

                return $this->redirectToRoute('payments_paginated', ['page' => $page]);
            }
        }
    }

    return $this->render('carregamentos/index.html.twig', [
        'payments' => $payments,
        'form' => $form->createView(),
    ]);
}

存储库

namespace App\Repository;

use App\Entity\Custom\Contratos;

...
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;

class ContractsRepository extends ServiceEntityRepository

    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Contracts::class);
    }

    /**
     * @return Contracts Returns the Contracts object for the ClientId
     */
    public function fetchMainByClient($value): ?Contracts
    {
        return $this->createQueryBuilder('c')
            ->andWhere('c.clientid = :val')
            ->andWhere('c.type = \'Main\'')
            ->setParameter('val', $value)
            ->getQuery()
            ->getOneOrNullResult()
        ;
    }
}

学说配置

doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                driver: 'pdo_mysql'
                server_version: '5.6'
                charset: utf8
                default_table_options:
                    charset: utf8
                    collate: utf8_unicode_ci

                url: '%env(resolve:DATABASE_URL)%'

            custom:
                driver: 'pdo_mysql'
                server_version: '5.6'
                charset: utf8
                default_table_options:
                    charset: utf8
                    collate: utf8_unicode_ci

                url: '%env(resolve:DATABASE_CUSTOM_URL)%'
                mapping_types:
                    enum: string
                    set:  string

    orm:
        auto_generate_proxy_classes: '%kernel.debug%'
        default_entity_manager: default
        entity_managers:
            default:
                connection: default
                naming_strategy: doctrine.orm.naming_strategy.underscore
                mappings:
                    Main:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity'
                        prefix: 'App\Entity'
                        alias: Main
            custom:
                connection: custom
                naming_strategy: doctrine.orm.naming_strategy.underscore
                mappings:
                    Custom:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity/Custom'
                        prefix: 'App\Entity\Custom'
                        alias: Custom

具有 ORM 映射的实体 header

namespace App\Entity\Custom;

use Doctrine\ORM\Mapping as ORM;

/**
 * Contracts.
 *
 * @ORM\Table(name="CONTRACTS", indexes={@ORM\Index(name="clientid", columns={"clientid"})})
 * @ORM\Entity(repositoryClass="App\Repository\ContractsRepository")
 */
class Contracts
{
    ...
}

问题是您的默认连接将选取 App\Entity 中的所有实体以及任何子目录,例如 App\Entity\Custom。因此,您的自定义实体被映射到两个实体管理器。

服务存储库构造器只是查看每个管理器以查看它是否支持给定的实体。第一个找到的是存储库。

将 App\Entity\Custom 移动到类似 App\EntityCustom 的位置并调整配置。