具有多个数据库的 postgresql 上的 Symfony 6 学说问题 SQLSTATE[42P01]:未定义的表:7 ERROR

问题描述 投票:0回答:1

我的 Symfony 项目(sf v6)使用 postgresql/postgis 和 2 个数据库:主要一个包含特定业务数据,第二个称为 web-services 数据库,其公共数据在多个项目之间共享(有两个模式,主要是 gis其中包含 GIS 数据) 首先,我参考了https://symfony.com/doc/current/doctrine/multiple_entity_managers.html
并设置我的 config/package/doctrine.yaml :

doctrine:
    dbal:
        connections:
          default:
            url: '%env(resolve:DATABASE_URL)%'
            server_version: '13.5'
          web_services:
            url: '%env(resolve:DATABASE_WS_URL)%'
            server_version: '13.5'
        default_connection: default
    orm:
        default_entity_manager: default
        entity_managers:
            default:
              connection: default
              #auto_generate_proxy_classes: true # thow exception Unrecognized options
              #enable_lazy_ghost_objects: true # thow exception Unrecognized options
              report_fields_where_declared: true
              validate_xml_mapping: true
              naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
              auto_mapping: true
              mappings:
                  App:
                      is_bundle: false
                      dir: '%kernel.project_dir%/src/Entity'
                      prefix: 'App\Entity'
                      alias: App
                      type: attribute
              #profiling:            "%kernel.debug%" # thow exception Unrecognized options
              #profiling_collect_backtrace: '%kernel.debug%' # thow exception Unrecognized options
            web_services:
              connection: web_services
              mappings:
                  Web_services:
                      is_bundle: false
                      dir: '%kernel.project_dir%/src/Entity/WebServices'
                      prefix: 'App\Entity\WebServices'
                      alias: Web_services
                      type: attribute

when@test:
    doctrine:
        dbal:
            # "TEST_TOKEN" is typically set by ParaTest
            dbname_suffix: '_test%env(default::TEST_TOKEN)%'

when@prod:
    doctrine:
        orm:
            auto_generate_proxy_classes: false
            proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies'
            query_cache_driver:
                type: pool
                pool: doctrine.system_cache_pool
            result_cache_driver:
                type: pool
                pool: doctrine.result_cache_pool

    framework:
        cache:
            pools:
                doctrine.result_cache_pool:
                    adapter: cache.app
                doctrine.system_cache_pool:
                    adapter: cache.system

主要是dbalurlconnectiondirprefix

我可以毫无问题地访问default连接、实体、存储库!

我定义了两个实体来访问 web_services 连接数据:
第一个,翻译

// src/Entity/WebServices/Translate.php

namespace App\Entity\WebServices;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Id;

#[ORM\Entity(repositoryClass: 'App\Repository\WebServices\TranslateRepository')]
#[ORM\Table(name: "gis.translate")]
class Translate
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    private $translateId;

    #[ORM\Column(type: 'string', length: 255)]
    private $frValue;

    #[ORM\Column(type: 'string', length: 255)]
    private $gbValue;

    public function getTranslateId(): ?int
    {
        return $this->translateId;
    }

    // and others getters/setters
}

第二个,国家

// src/Entity/WebServices/Country.php

namespace App\Entity\WebServices;

use App\Repository\WebServices\CountryRepository;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Id;

#[ORM\Entity(repositoryClass: 'App\Repository\WebServices\CountryRepository')]
#[ORM\Table(name: "gis.country")]
class Country
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $countryId = null;

    #[ORM\Column(length: 2, nullable: true)]
    private ?string $isoCode = null;

    #[ORM\ManyToOne]
    #[ORM\JoinColumn(name: 'translate_id', referencedColumnName: 'translate_id', nullable: false)]
    private ?Translate $translate = null;

    public function getCountryId(): ?int
    {
        return $this->country_id;
    }

    // and others getters/setters
}

请注意,web_services表使用tablename_id,而不仅仅是id

此时,如果我运行(在我的 sf docker 容器中,postgresql 在另一个容器中):

php bin/console dbal:run-sql 'SELECT * FROM translate'
主数据库转换表,或
php bin/console dbal:run-sql --connection web_services 'SELECT * FROM gis.translate'
用于 web_services 数据库转换表,
它运行正确!

如果我在 src/Controller/WebServices/CountryController 中调用

EntityManager
getClassMetadata 方法,它也会在 LocationCountryController 控制器中正确运行:

[…]
use Doctrine\ORM\EntityManagerInterface;
[…]

#[Route(path: '/location/country')]
class LocationCountryController extends AbstractController
{
    #[Route(path: '/', name: 'location_country_index', methods: ['GET'])]
    public function index(EntityManagerInterface $web_servicesEntityManager): Response
    {
        $ctableName = $web_servicesEntityManager->getClassMetadata(Country::class);
        $ttableName = $web_servicesEntityManager->getClassMetadata(Translate::class);
        dd($ctableName, $ttableName);
    }

    //[…]
}

如果我运行,总是在 src/Controller/WebServices/CountryController:

class LocationCountryController extends AbstractController
{
    #[Route(path: '/', name: 'location_country_index', methods: ['GET'])]
    public function index(EntityManagerInterface $web_servicesEntityManager): Response
    {
        $connection = $doctrine->getConnection('web_services');
        $countries = $connection->fetchAllAssociative('SELECT * FROM country c JOIN translate t ON c.translate_id=t.translate_id LIMIT 20');
        dd($countries);
    // […]

它返回了 20 个具有正确翻译数据的国家!

但是一旦我想使用国家存储库,例如,总是在src/Controller/WebServices/CountryController

namespace App\Controller;

use App\Entity\WebServices\Country;
use App\Entity\WebServices\Translate;
use App\Repository\WebServices\CountryRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;

#[Route(path: '/location/country')]
class LocationCountryController extends AbstractController
{
    #[Route(path: '/', name: 'location_country_index', methods: ['GET'])]
    public function index(ManagerRegistry $doctrine, EntityManagerInterface $web_servicesEntityManager): Response
    {
        $repository = $web_servicesEntityManager->getRepository(Country::class);
        $countries = $repository->findAll(); // ->find(1) returns same error
        dd($countries);
        // or
        $countriesRepository = $doctrine->getRepository(Country::class, 'web_services');
        dd($countriesRepository->findAll());
//[…]

我有错误:

An exception occurred while executing a query: SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "gis.country" does not exist

这是我的src/Repository/WebServices/CountryRepository.php:

namespace App\Repository\WebServices;

use App\Entity\WebServices\Country;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

/**
 * @extends ServiceEntityRepository<Country>
 *
 * @method Country|null find($id, $lockMode = null, $lockVersion = null)
 * @method Country|null findOneBy(array $criteria, array $orderBy = null)
 * @method Country[]    findAll()
 * @method Country[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class CountryRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Country::class);
    }

    // […]

    /**
     * @return country[] Returns an array of Country objects
     */
    public function findAll(): array
    {
        return $this->createQueryBuilder('c')
//          ->innerJoin('c.translate', 't')
//          ->addSelect('t')
//            ->orderBy('t.frValue', 'ASC')
            ->setMaxResults(5)
            ->getQuery()
            ->getResult()
        ;
    }

我将 symfony 更新到了最新的 6.3 版本,最新的 2.17 版本,但仍然有同样的错误!

在我要解决的搜索中,我发现了这篇文章:https://dba.stackexchange.com/questions/101570/error-42p01-relation-does-not-exist...权限不好...但我可以访问表,如果我不使用存储库!如果我搜索“postgresql Error 42P01”,我就会找到这篇文章:
PostgreSQL 错误:42P01:关系“[表]”不存在 我的

translate
country
表似乎命名正确。

编辑: 我尝试在实体中分离schematable

#[ORM\Table(schema: "sig", name: "country")] 
,不变!

postgresql symfony doctrine-orm doctrine symfony6
1个回答
0
投票

问题出在注册表的配置上。 Symfony 自动装配将搜索与配置匹配的第一个模式。 在这种情况下,App\Entity 永远是第一位的。

这个问题有两种解决方案:

首先是把最奇特的定义放在第一位。

另一种是将实体放在单独的文件夹中。

© www.soinside.com 2019 - 2024. All rights reserved.