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
我的设置正确还是我做的完全错误?我假设我定义了两个实体管理器和连接并告诉他们,他们必须处理哪些包.我确保每个包中只有一个数据库中的实体.
感谢您的帮助
解决方案这个问题看起来很老了,但一直没有人回答.我希望这个答案能帮助遇到这个问题的 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.
相关文章