Doctrine2の小ネタ(複数回Insertしたいとき編)

この記事は公開されてから半年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちわ、今回からは、Symfony2にデフォルトで付属しているORMであるDoctrine2の小ネタを紹介したいと思います。半分は備忘録になります

今日は、一度に多数のデータを挿入したいときはどうするの?です。基本的な使い方は
http://docs.symfony.gr.jp/symfony2/book/doctrine.htmlを参照してください。

エンティティ

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="product")
 */
class Product
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    protected $name;

    /**
     * @ORM\Column(type="decimal", scale=2)
     */
    protected $price;

    /**
     * @ORM\Column(type="text")
     */
    protected $description;
}

公式ページのまま利用しています。
こちらを普通にInsertするときは

単独Insert

public function createAction()
{
    $product = new Product();
    $product->setName('A Foo Bar');
    $product->setPrice('19.99');
    $product->setDescription('Lorem ipsum dolor');

    $em = $this->getDoctrine()->getEntityManager();
    $em->persist($product);
    $em->flush();

    return new Response('Created product');
}

です、では、複数個のProductを同時にInsertする場合はどうすればよいでしょう。
ポイントは、Doctrine2のエンティティマネージャーは

  • persistでは、オブジェクトを管理下におくだけ
  • flushで管理しているオブジェクトに対応した、SQL文を発行する

という点です、これに従って書いてみましょう

複数Insert

public function createManyAction()
{
    $em = $this->getDoctrine()->getEntityManager();
    $names        = Array("a", "b");
    $prices       = Array(100, 200);
    $descriptions = Array("hello", "goodbye");
    for($i = 0; $i < 2; $i++){
        $product = new Product();
        $product->setName($names[$i]);
        $product->setPrice($prices[$i]);
        $product->setDescription($descriptions[$i]);
        $em->persist($product);
    }
    $em->flush();

    return new Response('Created products');
}

となります。persistにはPDOでいうprepareの役割もあるので、この方法だとクエリーキャッシュを有効に利用できるそうです。http://doctrine-orm.readthedocs.org/en/latest/reference/batch-processing.html?highlight=batchなどが参考になるでしょうか。

一気にInsertするのではなく、forの中でInsertを実行したい場合、以下のようになります

複数Insert1回ごと

public function createManyAction()
{
    $em = $this->getDoctrine()->getEntityManager();
    $names        = Array("a", "b");
    $prices       = Array(100, 200);
    $descriptions = Array("hello", "goodbye");
    for($i = 0; $i < 2; $i++){
        $product = new Product();
        $product->setName($names[$i]);
        $product->setPrice($prices[$i]);
        $product->setDescription($descriptions[$i]);
        $em->persist($product);
        $em->flush();
        $em->clear();
    }

    return new Response('Created products');
}

SQLを発行するたびに、管理するオブジェクトをクリアしている点がポイントです。

今回はこれで失礼いたします。

投稿者プロフィール

開発 アルバイト
中の人には主に、
PHP・Symfony2系の人と
Ruby・Rails系の人がいます。
ときどきJavascript・データベースにも手を出すかもしれません。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Time limit is exhausted. Please reload CAPTCHA.