本文介绍了原则/符号4-保留子实体时避免重复输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有以下设置:我解析具有类似于此结构的api响应(我简化了一点):

I have the following setup: I parse an api response that has a structure similar to this (I oversimplify a bit):

{
    orders: [
        {
            // some data
            customers: [
                {
                    // some data
                    addresses: [
                        {
                            id: 436456445
                            // some data
                        },
                        // Other addresses
                     ]
                }
            ]                
        },
        {
            customers: [
                {
                    addresses: [
                        {
                            id: 436456445
                            // some data
                        }
                    ]
                }
            ]                
        }
    ]
}

请注意,特定地址在响应中出现了两次(同一个ID)。

Note that a specific address appears twice in the response (same id).

我深入研究(希望是正确的翻译)结构并制作实体。一切顺利,直到插入时的保存部分引发重复的键异常。

I deep travel (hope is the right translation) the structure and make entities. All goes well until the save part when inserting throws a duplicate key exception.

一个明显的解决方案是对结构进行规范化,以便地址位于命令之前,并重新映射周围的所有内容,但是正如我所说的,我简化了,实际案例具有数百种结构,这些结构可以动态映射到实体中,并可以手动处理许多特殊情况。这使得不可能寻找逻辑映射。捕获异常(如此处建议)失去了我的实体经理,这意味着从头开始处理相同的数据,出现相同的问题(对此不是100%的肯定……我在这里遗漏了什么吗?)。

An obvious solution would be to normalize structure so the addresses are before orders and remap everything around that, but as I said I oversimplified, the real case has hundreds of structures that map dynamically into entities with way to many special cases to be treated manually. That makes "hunting" for logical mapping impossible. Catching the exception (as suggested here insert ignore on duplicate entries in Doctrine2/Symfony2) looses my entity manager and would mean starting from scratch on same data, same problem emerging (not 100% sure on this... am I missing something here?).

我需要做的是在重复键上使用mysql插入[执行某些操作]或插入忽略(我更喜欢在重复键上插入,因为插入忽略会忽略太多东西)。知道怎么做吗?

What I need to do is make use of the mysql insert on duplicate key [do something] or insert ignore (I prefere insert on duplicate key because insert ignore ignores a bit too many things). Any idea how to do that?

重要说明:我正在持久化并刷新 order,其余实体则通过级联持久化。

Important note: I'm persisting and flushing the "order", rest of the entities are being persisted by cascade.

推荐答案

我想我用以下代码解决了我的问题(在我编写此答案时并没有进行优化,但目的很明确): / p>

I think I solved my issue with the following code (it is not optimized as I write this answer but the intent is rather clear):

protected function removeDuplicates($insertions) {
    foreach ($insertions as $key => $insertion) {
        $shortClassName = (new ReflectionClass($insertion))->getShortName();
        // TODO: The search can be heavily optimized
        foreach ($insertions as $possibleDupeKey => $possibleDupeInsertion) {
            $shortDupeClassName = (new ReflectionClass($insertion))->getShortName();
            // TODO: Treat case when unique is on a field not called 'id'
            if ($shortClassName === $shortDupeClassName && $insertion->getId() === $possibleDupeInsertion->getId() && $key !== $possibleDupeKey) {
                $this->em->remove($possibleDupeInsertion);
            }
        }
    }
}

protected function saveStuff($order) {
    $this->em->persist($order);
    $this->removeDuplicates($this->em->getUnitOfWork()->getScheduledEntityInsertions());
    $this->em->flush();
}

注意:我敢肯定,在90%的情况下,有更好的方法(但我认为在这种情况下我占10%,所以...共享10%的:P)。

Note: I'm sure that in 90% of cases there are better approaches (but I think I'm in the 10% with this particular case so... sharing for the 10% :P).

这篇关于原则/符号4-保留子实体时避免重复输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 11:19