使用与Doctrine的不同连接

时间:2015-09-04 07:40:47

标签: symfony doctrine-orm

我的应用程序从外部数据库中提取数据,然后在进行小规模处理后存储在应用程序数据库中。如何设置外部数据库的映射,因为它与实体无关?这就是我目前所拥有的:

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);
}

1 个答案:

答案 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列并避免字符串转换疯狂。 :)