バージョン選択

フォーラム

メニュー

オンライン状況

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

サイト内検索

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

その他

新規スレッドを追加する

スレッド表示 | 古いものから 前のトピック | 次のトピック | 下へ
投稿者 スレッド
nyorai
投稿日時: 2017/5/24 13:09
対応状況: −−−
仙人
登録日: 2015/8/21
居住地:
投稿: 302
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))のようにしておいてください。





hmorita_j
投稿日時: 2017/5/23 14:02
対応状況: −−−
長老
登録日: 2017/3/3
居住地: 沈黙の巨大都市松戸
投稿: 222
Re: 処理中に逐一DBに保存したい
ありがとうございます!!
公式ドキュメントをちゃんと読まないとダメですね・・・
助かりました!
nyorai
投稿日時: 2017/5/23 13:37
対応状況: −−−
仙人
登録日: 2015/8/21
居住地:
投稿: 302
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 12:34
対応状況: −−−
長老
登録日: 2017/3/3
居住地: 沈黙の巨大都市松戸
投稿: 222
Re: 処理中に逐一DBに保存したい
ありがとうございます!
MySQLで同じ挙動となりました。
これはトランザクションを一旦終わらせる、ということですよね?
もしプラグインでこのようなことをする場合、本体のトランザクション制御はそのままで、新たにコネクションを取得したほうが良いのかな?とか思ったのですがどうなんでしょう?
新たにコネクションを取得する方法もご存知でしたらご教示いただきたいです。
nyorai
投稿日時: 2017/5/22 12:45
対応状況: −−−
仙人
登録日: 2015/8/21
居住地:
投稿: 302
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/19 19:18
対応状況: −−−
長老
登録日: 2017/3/3
居住地: 沈黙の巨大都市松戸
投稿: 222
処理中に逐一DBに保存したい
お世話になっております。
3.0.11以降、「アプリケーションの開始/終了のタイミングでトランザクションのコントロールを行う」となりました。
この場合、処理の中で逐一DBに保存したい場合はどのようにしたら良いのでしょうか?
スレッド表示 | 古いものから 前のトピック | 次のトピック | トップ


 



ログイン


EC-CUBE公式 Amazon Payプラグイン

統計情報

総メンバー数は88,288名です
総投稿数は109,688件です

投稿数ランキング

1
seasoft
7365
2
468
3217
3
AMUAMU
2712
4
nanasess
2303
5
umebius
2085
6
yuh
1818
7
h_tanaka
1610
8
red
1567
9
mcontact
1240
10
tsuji
958
11
fukap
907
12
shutta
835
13
tao_s
796
14 ramrun 789
15 karin 689
16 sumida 641
17
homan
633
18 DELIGHT 572
19
patapata
502
20
flealog
485


ネットショップの壺

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

Copyright© EC-CUBE CO.,LTD. All Rights Reserved.