バージョン選択

フォーラム

メニュー

オンライン状況

39 人のユーザが現在オンラインです。 (25 人のユーザが フォーラム を参照しています。)
登録ユーザ: 0
ゲスト: 39
もっと...

PR

デザインテンプレート EC-CUBE3.0版が登場!
広告掲載について

サイト内検索

質問 > その他 > 処理中に逐一DBに保存したい

その他

新規スレッドを追加する

スレッド表示 | 新しいものから 前のトピック | 次のトピック | 下へ
投稿者 スレッド
hmorita_j
投稿日時: 2017/5/19 19:18
対応状況: −−−
一人前
登録日: 2017/3/3
居住地: 沈黙の巨大都市松戸
投稿: 130
処理中に逐一DBに保存したい
お世話になっております。
3.0.11以降、「アプリケーションの開始/終了のタイミングでトランザクションのコントロールを行う」となりました。
この場合、処理の中で逐一DBに保存したい場合はどのようにしたら良いのでしょうか?
nyorai
投稿日時: 2017/5/22 12:45
対応状況: −−−
長老
登録日: 2015/8/21
居住地:
投稿: 158
Re: 処理中に逐一DBに保存したい
処理中の間、setAutoCommit(true)に設定しておけばいけそうです。
一応検証コードを作成してみて、想定どおり登録できているのを確認しました。


    public function index(Application $app)
    {
        $app['orm.em']->getConnection()->setAutoCommit(true);

        $i = 30;
        $max = $i+10;
        for (; $i < $max; $i++) {
            $job = new Job();
            $job->setId($i);
            $job->setName($i);
            $job->setRank($i);

            $app['orm.em']->persist($job);
            $app['orm.em']->flush($job);

            if ($i == 35) {
                // 処理中にエラーを発生させる
                // 通常はすべてロールバックされるが、 id = 35まで登録されている.
                throw new NotFoundHttpException();
            }
        }

        $app['orm.em']->getConnection()->setAutoCommit(false);

        return $app->render('index.twig');
    }

SQLiteで試したので、他のDBだと挙動が異なるかもしれません。
hmorita_j
投稿日時: 2017/5/23 12:34
対応状況: −−−
一人前
登録日: 2017/3/3
居住地: 沈黙の巨大都市松戸
投稿: 130
Re: 処理中に逐一DBに保存したい
ありがとうございます!
MySQLで同じ挙動となりました。
これはトランザクションを一旦終わらせる、ということですよね?
もしプラグインでこのようなことをする場合、本体のトランザクション制御はそのままで、新たにコネクションを取得したほうが良いのかな?とか思ったのですがどうなんでしょう?
新たにコネクションを取得する方法もご存知でしたらご教示いただきたいです。
nyorai
投稿日時: 2017/5/23 13:37
対応状況: −−−
長老
登録日: 2015/8/21
居住地:
投稿: 158
Re: 処理中に逐一DBに保存したい
> これはトランザクションを一旦終わらせる、ということですよね?

そうですね。本体のトランザクションいったんコミットして、再度beginTransactionするような挙動になります。
※index_dev.phpでSQLログをみれば、どんなトランザクションになるかはわかると思います。

先程の検証コードは、正しくは以下になります。
プラグインでやると、先発・後続のプラグインのSQLにまで影響がでてしまうので、少しまずいかもしれませんね。


    public function index(Application $app)
    {
        // TransactionListener::onKernelRequestで開始されたトランザクションを一旦commit
        $app['orm.em']->getConnection()->commit();
        // auto commitを有効にして、flushごとにcommitされるようにする
        $app['orm.em']->getConnection()->setAutoCommit(true);

        $i = 30;
        $max = $i+10;
        for (; $i < $max; $i++) {
            $job = new Job();
            $job->setId($i);
            $job->setName($i);
            $job->setRank($i);

            $app['orm.em']->persist($job);
            $app['orm.em']->flush($job);

            if ($i == 35) {
                // 処理中にエラーを発生させる
                // 通常はすべてロールバックされるが、 id = 35まで登録されている.
                // throw new NotFoundHttpException();
            }
        }
        
        // auto commitを元に戻す
        $app['orm.em']->getConnection()->setAutoCommit(false);
        // トランザクションを開始する
        // このトランザクションは、TransactionListener::onKernelTerminateでcommitまたはrollbackされる
        $app['orm.em']->getConnection()->beginTransaction();
        
        return $app->render('index.twig');
    }


> 新たにコネクションを取得する方法もご存知でしたらご教示いただきたいです。

こんな感じのコードになります。
※Doctrineのドキュメントにありました。
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/getting-started.html


        // Doctrine/Ormのメタデータ設定を生成
        $config = \Doctrine\ORM\Tools\Setup::createYAMLMetadataConfiguration(array(
            $app['config']['root_dir'].'/src/Eccube/Resource/doctrine',
            $app['config']['root_dir'].'/src/Eccube/Resource/doctrine/master',
        ), $app['debug']);

        // 別コネクションでエンティティマネージャを生成
        $em = EntityManager::create($app['config']['database'], $config);

        // $app['eccube.repository.xxx']は既存のエンティティマネージャを使うので
        // レポジトリはgetRepositoryで個別に呼び出す必要がある
        $repository = $em->getRepository('Eccube\Entity\Master\Job');

        $job = $repository->find(1);
        dump($job);


hmorita_j
投稿日時: 2017/5/23 14:02
対応状況: −−−
一人前
登録日: 2017/3/3
居住地: 沈黙の巨大都市松戸
投稿: 130
Re: 処理中に逐一DBに保存したい
ありがとうございます!!
公式ドキュメントをちゃんと読まないとダメですね・・・
助かりました!
nyorai
投稿日時: 2017/5/24 13:09
対応状況: −−−
長老
登録日: 2015/8/21
居住地:
投稿: 158
Re: 処理中に逐一DBに保存したい
少しだけ注意が必要なのですが、本体のエンティティマネージャには、SoftDeleteFilter(検索時にdel_flg=0を自動でつける)や、SaveEventSubscriber(登録・更新時に自動でcreate_date, update_dateを設定する)が設定されています。

ここで生成したエンティティマネージャはまっさらな状態なので、そういった機構が効きません。

例えば、

$Customer = new Customer();
$Customer->setXXX()
...

$em->persist($Customer);
$em->flush($Customer);

のようなとき、本体のエンティティマネージャで処理していれば、create_date/update_dateは自動で設定されますが、新たに生成したエンティティマネージャだと、そういうことはやってくれません。


$Cusomer->setCreateDate(new \DateTime());


みたいに明示的にセットしておく必要があります。

検索するときも、単純にfindAll()とかすると、削除済みのレコードも取得できてしまうので、findBy(array('del_flg' => 0))のようにしておいてください。





スレッド表示 | 新しいものから 前のトピック | 次のトピック | トップ


 



ログイン


EC-CUBEペイメント

クレジットカード情報の非保持化対応

統計情報

総メンバー数は20,566名です
総投稿数は83,588件です

投稿数ランキング

1
seasoft
7331
2
AMUAMU
2712
3
nanasess
1662
4
yuh
1430
5
red
1076
6
fukap
907
7
shutta
827
8
468
801
9 ramrun 789
10
tsuji
784
11
umebius
725
12
tao_s
651
13 karin 641
14 sumida 638
15
homan
633
16 DELIGHT 571
17
patapata
502
18
flealog
483
19 tonton 436
20
ecbg
387


ネットショップの壺

EC-CUBEインテグレートパートナー

Copyright© LOCKON CO.,LTD. All Rights Reserved.