6

私はSymfony2とDoctrine2で少し遊んでいます。

たとえば、一意のタイトルを持つエンティティがあります。

class listItem
{
    /**
     * @orm:Id
     * @orm:Column(type="integer")
     * @orm:GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @orm:Column(type="string", length="255", unique="true")
     * @assert:NotBlank()
     */
    protected $title;

今、私はjsonをフェッチし、それらのアイテムでデータベースを更新しています:

$em = $this->get('doctrine.orm.entity_manager');
        
foreach($json->value->items as $item) {
    $listItem = new ListItem();
    $listItem->setTitle($item->title);
    $em->persist($listItem);
}

$em->flush();

初めて正常に動作します。しかし、2回目はSQLエラーが発生します(もちろん):Integrity constraint violation: 1062 Duplicate entry

時々私のjsonファイルが更新され、いくつかのアイテムは新しいものもあれば、そうでないものもあります。重複ファイルをスキップして新しいファイルを挿入するようにエンティティマネージャーに指示する方法はありますか?

これを行うための最良の方法は何ですか?

すべての助けをありがとう。不明な点がある場合はコメントを残してください

編集:

私にとってうまくいくのは、次のようなことです。

$uniqueness = $em->getRepository('ListItem')->checkUniqueness($item->title);
    if(false == $uniqueness) {
        continue;
    }

    $listItem = new ListItem();
    $listItem->setTitle($item->title);
    $em->persist($listItem);
    $em->flush();
}

checkUniquenessタイトルがすでにデータベースにあるかどうかをチェックするListItemリポジトリのメソッドです。

それはひどいです。これは、アイテムごとに2つのデータベースクエリです。これにより、このアクションに対する約85のデータベースクエリが発生します。

4

2 に答える 2

1

最初に現在のすべてのタイトルを配列に取得し、その配列内の現在のタイトルに対して挿入タイトルをチェックするのはどうですか

$existingTitles = $em->getRepository('ListItem')->getCurrentTitles();

foreach($json->value->items as $item) {
  if (!in_array($item->title, $existingTitles)) {
    $listItem = new ListItem();
    $listItem->setTitle($item->title);
    $em->persist($listItem);
  }
}

$em->flush();

単純にタイトルの配列を返すには、getCurrentTitles() を ListItem Repo に追加する必要があります。

これには追加の DB クエリが 1 つだけ必要ですが、現在のタイトルを配列に保持するためのメモリ消費量が増えます。ListItem のデータセットが非常に大きい場合、この方法で問題が発生する可能性があります。

毎回挿入するアイテムの数が多すぎない場合は、 getCurrentTitles() 関数を変更して、挿入しようとしているタイトルを持つすべてのアイテムをクエリすることができます。このようにして、返される $existingTiles の最大量は、挿入データ リストのサイズになります。次に、上記のようにチェックを実行できます。

// getCurrentTitles() - $newTitles is array of all new titles you want to insert
return $qb->select('title')
   ->from('Table', 't')
   ->in('t.title = ', $newTitles)
   ->getArrayResult();
于 2011-04-20T13:18:22.907 に答える
0

マネージャーに既に存在するエンティティを使用している場合は、それをマージする必要があります。

これが私がすることです(まだテストしていません):

$repository = $this->get('doctrine.orm.entity_manager');

foreach($json->value->items as $item) {
    $listItem = new ListItem();
    $listItem->setTitle($item->title);
    $em->merge($listItem); // return a managed entity
    // no need to persist as long as the entity is now managed
}

$em->flush();
于 2011-04-27T11:30:58.923 に答える