Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DoctrineWriter: fix setting associations #183

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

DoctrineWriter: fix setting associations #183

wants to merge 2 commits into from

Conversation

buddhaCode
Copy link

The associations set in loadAssociationObjectsToEntity() method will be overwritten by the original value/foreign key. This will lead to an Doctrine exception, coz Doctrine is expecting an entity object and not a scalar value.

The associations set in loadAssociationObjectsToEntity() method will be overwritten by the original value/foreign key. This will lead to an Doctrine exception, coz Doctrine is expecting an entity object and not a scalar value.
@buddhaCode buddhaCode changed the title prevent entity associations from beeing overwritten Edit DoctrineWriter: fix setting associations Apr 6, 2015
@buddhaCode buddhaCode changed the title Edit DoctrineWriter: fix setting associations DoctrineWriter: fix setting associations Apr 6, 2015
@Baachi
Copy link
Collaborator

Baachi commented Apr 7, 2015

Can you provide a failing test case?

@buddhaCode
Copy link
Author

Sorry, what do you mean?

@Baachi
Copy link
Collaborator

Baachi commented Apr 7, 2015

Can you provide a short snippet which shows the error, so i can reproduce your issue.

@buddhaCode
Copy link
Author

Sure.

I have a target model Store with an association to a model Industry

CSV source:

Industry
id: 1 name: industry1

Store
id: 1 name: store1 industry: 1

Here is the Error:

Found entity of type on association Shopware\CustomModels\StoreLocator\Store#industry, but expecting Shopware\CustomModels\StoreLocator\Industry in vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php on line 783
Stack trace:
#0 vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php(679): Doctrine\ORM\UnitOfWork->computeAssociationChanges(Array, 1)
#1 vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php(740): Doctrine\ORM\UnitOfWork->computeChangeSet(Object(Doctrine\ORM\Mapping\ClassMetadata), Object(Shopware\CustomModels\StoreLocator\Store))
#2 vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php(297): Doctrine\ORM\UnitOfWork->computeChangeSets()
#3 vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php(389): Doctrine\ORM\UnitOfWork->commit(NULL)
#4 Shopware/Plugins/Local/Frontend/NetcomTypo3StoreLocator/vendor/ddeboer/data-import/src/Ddeboer/DataImport/Writer/DoctrineWriter.php(179): Doctrine\ORM\EntityManager->flush()
#5 Shopware/Plugins/Local/Frontend/NetcomTypo3StoreLocator/vendor/ddeboer/data-import/src/Ddeboer/DataImport/Workflow.php(304): Ddeboer\DataImport\Writer\DoctrineWriter->finish()
#6 Shopware/Plugins/Local/Frontend/NetcomTypo3StoreLocator/Controllers/Frontend/StoreImport.php(312): Ddeboer\DataImport\Workflow->process()
#7 Shopware/Plugins/Local/Frontend/NetcomTypo3StoreLocator/Controllers/Frontend/StoreImport.php(52): Shopware_Controllers_Frontend_StoreImport->importStores('m...')
#8 Enlight/Controller/Action.php(159): Shopware_Controllers_Frontend_StoreImport->importAction()
#9 Enlight/Controller/Dispatcher/Default.php(528): Enlight_Controller_Action->dispatch('importAction')
#10 Enlight/Controller/Front.php(228): Enlight_Controller_Dispatcher_Default->dispatch(Object(Enlight_Controller_Request_RequestHttp), Object(Enlight_Controller_Response_ResponseHttp))
#11 Shopware/Kernel.php(141): Enlight_Controller_Front->dispatch()
#12 vendor/symfony/http-kernel/Symfony/Component/HttpKernel/HttpCache/HttpCache.php(472): Shopware\Kernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#13 Shopware/Components/HttpCache/AppCache.php(256): Symfony\Component\HttpKernel\HttpCache\HttpCache->forward(Object(Symfony\Component\HttpFoundation\Request), true, NULL)
#14 vendor/symfony/http-kernel/Symfony/Component/HttpKernel/HttpCache/HttpCache.php(429): Shopware\Components\HttpCache\AppCache->forward(Object(Symfony\Component\HttpFoundation\Request), true)
#15 vendor/symfony/http-kernel/Symfony/Component/HttpKernel/HttpCache/HttpCache.php(329): Symfony\Component\HttpKernel\HttpCache\HttpCache->fetch(Object(Symfony\Component\HttpFoundation\Request), true)
#16 Shopware/Components/HttpCache/AppCache.php(178): Symfony\Component\HttpKernel\HttpCache\HttpCache->lookup(Object(Symfony\Component\HttpFoundation\Request), true)
#17 vendor/symfony/http-kernel/Symfony/Component/HttpKernel/HttpCache/HttpCache.php(193): Shopware\Components\HttpCache\AppCache->lookup(Object(Symfony\Component\HttpFoundation\Request), true)
#18 Shopware/Components/HttpCache/AppCache.php(113): Symfony\Component\HttpKernel\HttpCache\HttpCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#19 shopware.php(109): Shopware\Components\HttpCache\AppCache->handle(Object(Symfony\Component\HttpFoundation\Request))
#20 {main}

And here is the xDebug output.

bildschirmfoto 2015-04-09 um 11 27 43

$value should not be "1". It should be an object of type Industry. Actually, all associations were already set in the loadAssociationObjectsToEntity() method, which was called directly before updateEntity() method. So the associations does not have to be set again.

@webdevilopers
Copy link

👍 Fixes #188.

@Baachi
Copy link
Collaborator

Baachi commented Apr 21, 2015

This might fix your issue but as travis reported it completely break the current workflow. I can't really produce your issue. @webdevilopers Maybe you can submit a PR with an testcase which demostrate the bug.

@webdevilopers
Copy link

As mentioned in #188 (comment) I was wondering why the fix worked. My issue looked more like a reading - not writing - issue in #188.

I will try the same import with a new xlsx file from scratch to prevent any formatting that is done by the tool that exported it, @Baachi .

@webdevilopers
Copy link

I played around with the xlsx file. I removed some lines and tried again.
After some attempts it looks like my script will break every 20 items.
Is there a number set for this batch action?

Here are the first rows of my xlsx file:
bildschirmfoto vom 2015-04-22 10 36 44

The strange thing is the debug output. While this output relates to the first element with ID 3152

 at ORMInvalidArgumentException ::invalidAssociation (object(ClassMetadata), array(
'fieldName' => 'creditAccount', 'joinColumns' => array(array('name' => 'credit_account_id', 'unique' => false, 'nullable' => true, 'onDelete' => null, 'columnDefinition' => null, 'referencedColumnName' => 'id')), 'cascade' => array(), 'inversedBy' => 'creditAccountJournals',
'targetEntity' => 'AppBundle\Entity\AccountsCode', 'fetch' => '2', 'type' => '2', 'mappedBy' => null, 'isOwningSide' => true, 'sourceEntity' => 'AppBundle\Entity\Journal', 'isCascadeRemove' => false, 'isCascadePersist' => false, 'isCascadeRefresh' => false, 'isCascadeMerge' => false, 'isCascadeDetach' => false, 'sourceToTargetKeyColumns' => array('credit_account_id' => 'id'),
'joinColumnFieldNames' => array('credit_account_id' => 'credit_account_id'), 'targetToSourceKeyColumns' => array('id' => 'credit_account_id'), 'orphanRemoval' => false),
'3152')

in vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 844  +
at UnitOfWork ->computeAssociationChanges (array(
'fieldName' => 'creditAccount', 'joinColumns' => array(array('name' => 'credit_account_id', 'unique' => false, 'nullable' => true, 'onDelete' => null, 'columnDefinition' => null, 'referencedColumnName' => 'id')), 'cascade' => array(), 'inversedBy' => 'creditAccountJournals',
'targetEntity' => 'AppBundle\Entity\AccountsCode', 'fetch' => '2', 'type' => '2', 'mappedBy' => null, 'isOwningSide' => true, 'sourceEntity' => AppBundle\Entity\Journal', 'isCascadeRemove' => false, 'isCascadePersist' => false, 'isCascadeRefresh' => false, 'isCascadeMerge' => false, 'isCascadeDetach' => false, 'sourceToTargetKeyColumns' => array('credit_account_id' => 'id'),
'joinColumnFieldNames' => array('credit_account_id' => 'credit_account_id'), 'targetToSourceKeyColumns' => array('id' => 'credit_account_id'), 'orphanRemoval' => false),
'3152')
in vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 741

some outputs later relates to the last item with IDs 9008 and 10130

at DoctrineWriter ->writeItem (array('' => null,
'creditAccount' => '9008', 'debitAccount' => '10130'))
in vendor/ddeboer/data-import/src/Ddeboer/DataImport/Workflow.php at line 261

All the IDs are quoted so I guess they are interpreted as strings.

My Mapping:

        $converter = new MappingItemConverter();
        $converter
            ->addMapping('Belegdat.', 'documentDate')
            ->addMapping('Sollkto', 'creditAccount')
            ->addMapping('Habenkto', 'debitAccount')
        ;
$workflow->addItemConverter($converter);

And my entity mapping:

class Journal
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="date", name="document_date")
     */
    private $documentDate;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\AccountsCode", inversedBy="creditAccountJournals")
     * @ORM\JoinColumn(name="credit_account_id", referencedColumnName="id", nullable=true)
     */
    private $creditAccount;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\AccountsCode", inversedBy="debitAccountJournals")
     * @ORM\JoinColumn(name="debit_account_id", referencedColumnName="id", nullable=true)
     */
    private $debitAccount;
}

Pretty basic.

@Baachi
Copy link
Collaborator

Baachi commented Apr 22, 2015

Ah okay i think your issue is related to the doctrine entity manager clear behaviour. The DoctrineWriter have a batch processor builtin. If the batch of 20 items are reached, the DoctrineWriter will flush the entity manager and remove all objects in the entity manager.

This should solve your problem:

use Ddeboer\DataImport\Writer\DoctrineWriter as BaseDoctrineWriter;

class DoctrineWriter extends BaseDoctrineWriter {
     public function flushAndClear()
     {
              $this->entityManager->flush();
     }
}

@webdevilopers
Copy link

I'm currently not working on that project but this looks like the main issue, thanks @Baachi .
Is this behaviour documented anywhere? Is it a real use case regarding my use case?
Should I open a new one or will the BaseDoctrineWriter be updated with a different fix for this original issue by @buddhaCode ?

@Baachi
Copy link
Collaborator

Baachi commented May 27, 2015

A fix is difficult because it depends on your needs.
We are working on the documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants