Symfony2 - Doctrine2:跨数据库连接列抛出映射异常 [英] Symfony2 - Doctrine2: Cross-Database Join Column throws Mapping-Exception

查看:21
本文介绍了Symfony2 - Doctrine2:跨数据库连接列抛出映射异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,想在两个实体之间建立连接.实体位于不同的数据库中:

这是我设置数据库配置的方法:

学说:数据库:default_connection: 默认连接:默认:驱动程序:%database_driver%主机:%database_host%端口:%database_port%数据库名称:%database_name%用户:%database_user%密码:%database_password%字符集:UTF8映射类型:枚举:字符串数据仓库:驱动程序:%database_data_warehouse_driver%主机:%database_data_warehouse_host%端口:%database_data_warehouse_port%数据库名称:%database_data_warehouse_name%用户:%database_data_warehouse_user%密码:%database_data_warehouse_password%字符集:UTF8映射类型:枚举:字符串形式:auto_generate_proxy_classes: %kernel.debug%default_entity_manager:默认实体经理:默认:连接:默认映射:MyBundle1:~数据仓库:连接:数据仓库映射:MyBundle2:~

这些是我的实体:

命名空间 MyBundle1Entity;使用 MyBundle1EntityMyBundle2Entity;类 MyBundle1Entity{/*** @var 整数** @ORMColumn(name="id", type="integer", nullable=false)* @ORMId* @ORMGeneratedValue(strategy="IDENTITY")*/私人 $id;}命名空间 MyBundle2Entity;类 MyBundle2Entity{/*** @var 整数** @ORMColumn(name="id", type="integer", nullable=false)* @ORMId* @ORMGeneratedValue(strategy="IDENTITY")*/私人 $id;/*** @var MyBundle1Entity** @ORMManyToOne( targetEntity="MyBundle1EntityMyBundle1Entity")* @ORMJoinColumn(name="my_bundle1_entity_id", nullable=true)*/私人 $myBundle1Entity;}

当我尝试使用 science:schema:update 命令时,出现错误:

php app/console 原则:schema:create --dump-sql --em=data_warehouse

错误:

[DoctrineCommonPersistenceMappingMappingException]
在链配置的命名空间 MyBundle2EntityBundle2Entity

中找不到类MyBundle1EntityBundle1Entity"

我的设置正确还是我做的完全错误?我假设我定义了两个实体管理器和连接并告诉他们,他们必须处理哪些包.我确保每个包中只有一个数据库中的实体.

感谢您的帮助

解决方案

这个问题看起来很老了,但一直没有人回答.我希望这个答案能帮助遇到这个问题的 Google 同事.

您不能跨实体管理器在实体之间建立直接关系.但是,如果捆绑包共享同一个实体管理器,则您可以在它们之间建立关系.

使用相同实体管理器的 2 个实体之间的关系 [2.2+]:

查看有关该问题的 Symfony 文档

本质上,在 Bundle1 中,创建一个接口,然后在您的实体上实现它.在 Bundle2 中,将您的 @ManyToOne 注释链接到接口而不是实体本身.然后,在配置中告诉Symfony如何解析接口.

捆绑包 1:

捆绑 2:

应用配置:

# app/config/config.yml教义:# ....形式:# ....resolve_target_entities:MyBundle1EntityBundle1EntityInterface: MyBundle1EntityBundle1Entity

使用不同实体管理器的 2 个实体之间的关系

因为实体不能直接绑定,你必须钩入 postLoad 事件来设置引用,同时手动持久化 id.请参阅 文档有关将 MongoDB 对象与 ORM 对象混合的示例和说明.

这是一个框架(删除了 getter/setter),使用了 2 个实体管理器:

实体:

myBundle1EntityId = $entity->getId();$this->myBundle1Entity = $entity;}}

事件监听器:

bundle1Em = $bundle1Em;}公共函数 postLoad(LifecycleEventArgs $eventArgs){$myBundle2Entity = $eventArgs->getEntity();$defaultEm = $eventArgs->getEntityManager();$myBundle2EntityReflProp = $defaultEm->getClassMetadata('EntityMyBundle2Entity')->reflClass->getProperty('myBundle1Entity');$myBundle2EntityReflProp->setAccessible(true);$myBundle2EntityReflProp->setValue($myBundle1Entity, $this->bundle1Em->getReference('EntityMyBundle1Entity', $myBundle2Entity->getMyBundle1Id()));}}

显然,您必须注册事件侦听器并将捆绑包 1 的实体管理器作为参数传递.

Hi want to make a join between two entities. The entities are in different databases:

Here is how I set up my database config:

doctrine:
    dbal:
    default_connection: default
    connections:
        default:
            driver:   %database_driver%
            host:     %database_host%
            port:     %database_port%
            dbname:   %database_name%
            user:     %database_user%
            password: %database_password%
            charset:  UTF8
            mapping_types:
                enum: string
        data_warehouse:
            driver:   %database_data_warehouse_driver%
            host:     %database_data_warehouse_host%
            port:     %database_data_warehouse_port%
            dbname:   %database_data_warehouse_name%
            user:     %database_data_warehouse_user%
            password: %database_data_warehouse_password%
            charset:  UTF8
            mapping_types:
                enum: string

    orm:
    auto_generate_proxy_classes: %kernel.debug%

    default_entity_manager: default

    entity_managers:
        default:
            connection: default
            mappings:
                MyBundle1: ~


        data_warehouse:
            connection: data_warehouse
            mappings:
                MyBundle2: ~

And these are my entities:

namespace MyBundle1Entity;
use MyBundle1EntityMyBundle2Entity;
class MyBundle1Entity
{

    /**
     * @var integer
     *
     * @ORMColumn(name="id", type="integer", nullable=false)
     * @ORMId
     * @ORMGeneratedValue(strategy="IDENTITY")
     */
    private $id;
}


namespace MyBundle2Entity;
class MyBundle2Entity
{

    /**
     * @var integer
     *
     * @ORMColumn(name="id", type="integer", nullable=false)
     * @ORMId
     * @ORMGeneratedValue(strategy="IDENTITY")
     */
    private $id;


   /**
     * @var MyBundle1Entity
     *
     * @ORMManyToOne( targetEntity="MyBundle1EntityMyBundle1Entity")
     * @ORMJoinColumn(name="my_bundle1_entity_id",  nullable=true)
     */
    private $myBundle1Entity;
}

When I try to use the doctrine:schema:update command, I get an error:

php app/console doctrine:schema:create --dump-sql --em=data_warehouse

Error:

[DoctrineCommonPersistenceMappingMappingException]
The class 'MyBundle1EntityBundle1Entity' was not found in the chain configured namespaces MyBundle2EntityBundle2Entity

Is my setup correct or am I doeing something completely wrong? I assume that I define two entity managers and there connections and tell them, what bundles they have to handle. I ensure that there are only entities from one database in each bundle.

Thanks for your help

解决方案

It looks like this question is old, but was never answered. I'm hoping this answer helps fellow Googlers stumbling across this question.

You can't set up a direct relationship between entities across entity managers. You can set up relationships across bundles, though, if they share the same entity manager.

Relationships between 2 entities using the same entity manager [2.2+]:

Have a look at the Symfony docs on the issue

Essentially, in Bundle1, create an interface, then implement it on your entity. In Bundle2, link your @ManyToOne annotation to the interface instead of the entity itself. Then, tell Symfony in the config how to resolve the interface.

Bundle1:

<?php

// src/My/Bundle1/Entity/Bundle1Entity.php

namespace MyBundle1Entity;

use MyBundle1EntityMyBundle2Entity; // <-- NOT NEEDED

interface Bundle1EntityInterface {}

class MyBundle1Entity implements Bundle1EntityInterface
{
    // ...
}

Bundle2:

<?php

// src/My/Bundle2/Entity/Bundle2Entity.php

namespace MyBundle2Entity;
class MyBundle2Entity
{
    // ...

    /**
     * @var MyBundle1Entity
     *
     * @ORMManyToOne(targetEntity="MyBundle1EntityBundle1EntityInterface")
     * @ORMJoinColumn(name="my_bundle1_entity_id", nullable=true)
     */
    private $myBundle1Entity;
}

App Config:

# app/config/config.yml
doctrine:
    # ....
    orm:
        # ....
        resolve_target_entities:
            MyBundle1EntityBundle1EntityInterface: MyBundle1EntityBundle1Entity

Relationships between 2 entities using a different entity manager

Because the entities cannot be tied directly, you must hook into the postLoad event to set up the reference, while persisting the id manually. See docs for an example and explanation of blending a MongoDB object with an ORM object.

Here's a skeleton (getters/setters removed), using 2 entity managers:

Entities:

<?php

// src/My/Bundle1/Entity/Bundle1Entity.php

namespace MyBundle1Entity;

class MyBundle1Entity
{
    /**
     * @var integer
     *
     * @ORMColumn(name="id", type="integer", nullable=false)
     * @ORMId
     * @ORMGeneratedValue(strategy="IDENTITY")
     */
    private $id;
}


// src/My/Bundle2/Entity/Bundle2Entity.php

namespace MyBundle2Entity;
class MyBundle2Entity
{
    /**
     * @var integer
     *
     * @ORMColumn(name="id", type="integer", nullable=false)
     * @ORMId
     * @ORMGeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var integer
     *
     * @ORMColumn(type="integer")
     */
    private $myBundle1EntityId;

    /**
     * @var MyBundle1Entity
     */
    private $myBundle1Entity;

    public function setMyBundle1Entity($entity)
    {
        $this->myBundle1EntityId = $entity->getId();
        $this->myBundle1Entity = $entity;
    }
}

Event Listener:

<?php

use DoctrineORMEntityManager;
use DoctrineORMEventLifecycleEventArgs;

class MyEventSubscriber
{
    public function __construct(EntityManager $bundle1Em)
    {
        $this->bundle1Em = $bundle1Em;
    }

    public function postLoad(LifecycleEventArgs $eventArgs)
    {
        $myBundle2Entity = $eventArgs->getEntity();
        $defaultEm = $eventArgs->getEntityManager();
        $myBundle2EntityReflProp = $defaultEm->getClassMetadata('EntityMyBundle2Entity')
            ->reflClass->getProperty('myBundle1Entity');
        $myBundle2EntityReflProp->setAccessible(true);
        $myBundle2EntityReflProp->setValue(
            $myBundle1Entity, $this->bundle1Em->getReference('EntityMyBundle1Entity', $myBundle2Entity->getMyBundle1Id())
        );
    }
}

Obviously, you'd have to register the event listener and pass bundle 1's entity manager as an argument.

这篇关于Symfony2 - Doctrine2:跨数据库连接列抛出映射异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆