首页 > 解决方案 > 在特定实体对象的存储库中使用不同的实体管理器

问题描述

我已按照手册中的如何使用多个实体管理器和连接一章在我的应用程序中配置和使用不同的实体管理器,因为某些实体存储在不同的数据库服务器中。

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

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

执行 'SELECT ... FROM CONTRACTS c0_ WHERE c0_.ClientId = 时发生异常?AND c0_.Type = 'Main'' 带参数 [35736]:

SQLSTATE [42S02]:未找到基表或视图:1146 表 'DEFAULTDB.CONTRACTS' 不存在

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

我究竟做错了什么?

这是控制器、存储库的代码和合同实体标头,以及原则配置。这不是真实的,但它是相似的。

控制器

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 映射的实体标头

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
{
    ...
}

标签: phpsymfonydoctrine-ormsymfony4

解决方案


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

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

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


推荐阅读