2016-04-09 32 views
2

我想批量導入XML文件中的Doctrine實體。堅持一個實體,而不將其附加到EntityManager

的XML文件可能會非常大(可達100萬個單位),所以我不能堅持我的所有實體的傳統方式:

$em->beginTransaction(); 

while ($entity = $xmlReader->readNextEntity()) { 
    $em->persist($entity); 
} 

$em->flush(); 
$em->commit(); 

我很快就會超過我的內存限制,並學說並不是真正用於處理那麼多管理實體的。

我不需要將更改跟蹤到持久實體,只是爲了堅持它們;因此我不希望它們由EntityManager管理。

是否可以堅持實體而不讓它們由EntityManager管理?


這使我想到的第一個選擇是堅持後立即取下它:

$em->beginTransaction(); 

while ($entity = $xmlReader->readNextEntity()) { 
    $em->persist($entity); 
    $em->flush($entity); 
    $em->detach($entity); 
} 

$em->commit(); 

但是,這是在教義相當昂貴,而且會進口放緩。


另一種選擇是將數據直接插入使用Connection對象和事先準備好的聲明的數據庫,但我喜歡實體的抽象,在理想情況下喜歡直接存儲對象

回答

2

而不是使用detachflush每個插入之後,你可以調用clear(其分離從經理所有實體),並分批flush,這應該是顯著快:

在學說

批量插入是最好的分批執行,取得了 EntityManager的事務性寫後行爲的優勢。以下代碼顯示了插入批次大小爲20的10000 對象的示例。您可能需要嘗試使用批量大小 以查找最適合您的大小。大批量 大小意味着更多內部準備好的語句重用,但也意味着更多 刷新期間的工作。

https://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/batch-processing.html

如果可能的話,我建議批量操作避免交易因爲他們往往慢下來:

//$em->beginTransaction(); 
$i = 0; 

while ($entity = $xmlReader->readNextEntity()) { 
    $em->persist($entity); 
    if(++$i % 20 == 0) { 
     $em->flush(); 
     $em->clear(); // detaches all entities 
    } 
} 

$em->flush(); //Persist objects that did not make up an entire batch 
$em->clear(); 

//$em->commit(); 
+1

我希望離開的EntityManager在其當前狀態,但它不是畢竟是一件大事。我也已經看到'clear()'接受一個可選的類名來僅僅分離一個給定類的實體,在這種情況下可能會有所幫助。所以我想這是目前唯一的方法! – Benjamin