我的应用程序从外部数据库中提取数据,然后在进行小规模处理后存储在应用程序数据库中。如何设置外部数据库的映射,因为它与实体无关?这就是我目前所拥有的:
dbal:
default_connection: default
types:
json: Sonata\Doctrine\Types\JsonType
connections:
default:
driver: pdo_mysql
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
rnr:
driver: pdo_mysql
host: "%database_host2%"
port: "%database_port2%"
dbname: "%database_name2%"
user: "%database_user2%"
password: "%database_password2%"
charset: UTF8
orm:
default_entity_manager: default
auto_generate_proxy_classes: "%kernel.debug%"
entity_managers:
default:
connection: default
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
rnr:
connection: rnr
mappings:
AppBundle: ~
通过此实现,我收到以下错误:
[Doctrine\ORM\ORMException]
Unknown Entity namespace alias 'AppBundle'.
以下是我实现该功能的方法:
protected function execute(InputInterface $input, OutputInterface $output)
{
$em = $this->getContainer()->get('doctrine')->getManager();
$q = $em->createQueryBuilder();
$q->select('t')->from('AppBundle:TransactionSync', 't')->orderBy('t.id', 'DESC')->setMaxResults(1);
$sync = $q->getQuery()->getResult();
$em1 = $this->getContainer()->get('doctrine')->getManager('rnr');
$conn = $em1->getConnection();
$query = "SELECT id, merchant, client, phone, traderTransIdent AS member_id, transaction_id, transaction_type_id, value AS amount, points, DATE_FORMAT(STR_TO_DATE( transaction_date, '%d-%m-%Y' ), '%Y-%m-%d') AS transaction_date FROM merchant_transactions WHERE id > ". $sync->getId();
$stmt = $conn->prepare($query);
$stmt->execute();
$results = $stmt->fetchAll();
if(count($results) > 1)
{
$ts = new TransactionSync();
$ts->setStartTime(new \DateTime());
$id = 0;
foreach($results as $result)
{
$transaction_type = $em->getRepository('AppBundle:TransactionType')->find($result['transaction_type_id']);
$member = $em->getRepository('AppBundle:Member')->find($result['member_id']);
$transaction = new Transaction();
$transaction->setAmount($result['amount']);
$transaction->setPoints($result['points']);
$transaction->setClient($result['client']);
$transaction->setPhone($result['phone']);
$transaction->setTransactionId($result['transaction_id']);
$transaction->setTransactionDate(new \DateTime($result['transaction_date']));
$transaction->setTransactionType($transaction_type);
$transaction->setMember($member);
$em->persist($transaction);
$id = $result['id'];
}
$ts->setLastId($id);
$ts->setRecords(count($results));
$ts->setEndTime(new \DateTime());
$em->persist($ts);
$em->flush();
}
$output->writeln($text);
}
答案 0 :(得分:1)
不幸的是,您不能将auto_mapping
与多个连接一起使用,并且您无法将相同的Bundle和/或相同的别名映射到不同的连接。 Doctrine可能会在AppBundle
中查找default
个实体,完全忽略rnr
;检查Doctrine run所知的所有实体:
app/console doctrine:mapping:info
并查看您的课程是否正确列出。
要解决您的问题,您需要将TransactionSync实体移出AppBundle。例如,您可以创建一个' ExtEntity'目录并将配置更改为以下内容:
orm:
default_entity_manager: default
auto_generate_proxy_classes: "%kernel.debug%"
entity_managers:
default:
connection: default
naming_strategy: doctrine.orm.naming_strategy.underscore
mappings:
AppBundle: ~
rnr:
connection: rnr
mappings:
ExtEntityMapping:
arbitrary_key:
type: xml # or annotation/yml
dir: %kernel.dir%/../src/AppBundle/ExtEntity
prefix: AppBundle\ExtEntity\
alias: ExtEntity
为了避免一些头痛,您还可以使用Registry:: getEntityManagerForClass
方法为对象检索正确的ObjectManager
。
例如,您可以在代码中执行以下操作:
$registry = $this->getContainer()->get('doctrine');
$transSyncManager = $registry->getEntityManagerForClass('ExtEntity:TransactionSync');
$transTypeManager = $registry->getEntityManagerForClass('AppBundle:TransactionType');
偏离轨道,请注意您正在以错误的方式使用预准备语句,这很容易进行SQL注入(如果ID总是由DBMS生成,则可能不会;使用这样的参数:
$query = "SELECT id, merchant, client, phone, traderTransIdent AS member_id, transaction_id, transaction_type_id, value AS amount, points, DATE_FORMAT(STR_TO_DATE( transaction_date, '%d-%m-%Y' ), '%Y-%m-%d') AS transaction_date FROM merchant_transactions WHERE id > :minId";
$stmt = $conn->prepare($query);
$stmt->execute(array('minId' => $sync->getId());
甚至更好 - 如果你可以修改你的数据库模式 - 使用DateTime作为transaction_date
列并避免字符串转换疯狂。 :)