2016-06-11 163 views
1

比方說,我有一個腳本行插入數據庫,它看起來像這樣:Doctrine如何處理多個請求?

/* $start is some GET parameter. Any number between 0 and 9900 */ 

/* Select all objects with ids between $start and $start+99 
and put their ids into $ids array */ 
$qb->select('object'); 
$qb->from('AppBundle:Object','object'); 
$qb->where("object.id >= $start"); 
$qb->andWhere("object.id < $start+100"); 
$objects = $qb->getQuery()->getResult(); 

$ids = array(); 
foreach($objects AS $object) { 
    $ids[] = $object->getId(); 
} 

/* Create missing objects and insert them into database */ 
for($id=$start; $id<$start+100; ++$id) { 
    if(in_array($id, $ids)) continue; 
    /* Some calculations */ 
    $createdObject = new Object($id, $some, $data); 
    $em->persist($createdObject); 
} 
$em->flush(); 

現在想象一下,有沒有對象(表是明確的)和一個用戶進入與啓動站點= 0 。該腳本需要2秒鐘才能完成。在完成之前 - 另一個用戶以start = 50進入站點。

我不知道究竟會在這樣的情況發生,但我認爲persume:

  1. 首先用戶輸入 - 在$ ids數組是空的,腳本ID爲0-99生成對象。

  2. 第二個用戶輸入 - $ em-> flush形式第一個入口尚未調用,這意味着$ ids數組仍然是空的(我猜?)。該腳本正在生成ID爲50-149的對象

  3. 第一個用戶入口有第一個$ em-> flush()調用。它將對象0-99插入到數據庫中。

  4. 還有一個來自第二個用戶入口的$ em-> flush()調用。它試圖將對象50-149插入到數據庫中。它失敗了,因爲ID = 50的對象已經存在於數據庫中。結果它實際上並沒有將任何東西插入到數據庫中。

這是真的會發生什麼?如果是這樣 - 如何防止它,以及只將那些缺少的對象插入到數據庫中的最佳方法是什麼? @edit:這只是一個exmaple代碼,但在實際腳本中,id實際上是3列(x,y,z),而對象是地圖上的字段。這個腳本的目的是我想要一個巨大的地圖,它會花費太多的時間來一次生成它。所以我只想生成一點點,然後只在某些用戶試圖訪問它們時創建缺失的部分。在某個時候,整個地圖將會被創建,但是這個過程會被錯開。

+0

http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/transactions-and-concurrency.html – ceejayoz

回答

1

你有2種不好的做法在這裏:

  1. 您前人的精力避免INSERT或UPDATE操作時,用戶進入您的網站(因爲它們是慢/昂貴的),尤其是如果它是關於像增加了許多對象數據庫這個腳本。它應該運行在某種cron腳本中,與您的網站用戶無關。
  2. 您不應該事先將ID分配給您的對象。將它保留爲空,Doctrine將爲您處理它。爲什麼你需要提前設置ID?

要回答您的問題 - 如果您爲具有預先分配的ID的對象調用$ em-> persist(),並且在數據庫中存在具有相同ID的另一個對象的情況下 - INSERT不會發生。相反,已存在的對象將使用來自新對象的數據進行更新(之後調用em-> flush())。因此,而不是2個對象(如預期的那樣),數據庫中只有1個。所以這就是爲什麼我真的懷疑你是否需要預先分配ID。你應該告訴我更多關於這個的目的:)

+0

其實,沒有。 '$ em-> persist()'不會在數據庫中產生'update'。根據[文檔](http://doctrine-orm.readthedocs。io/projects/doctrine-orm/en/latest/reference/working-with-objects.html#persisting-entities),如果X是一個分離的實體,則會在flush上引發異常。如果實體的ID相同已經存在於數據庫中,那麼這個新實體將從教條的角度來看是「分離的」實體。 – djxak

+0

在實際腳本中,id實際上是3列:x,y和z,它們是地圖上某個字段的座標。這個腳本的目的是我想要一個巨大的地圖,它會花費太多的時間來一次生成它。所以我只想生成一點點,然後只在某些用戶試圖訪問它們時創建缺失的部分。在某個時候,整個地圖將會被創建,但是這個過程會被錯開。 –