【问题标题】:ZF2, Oracle, SlmQueueDoctrine, ClearObjectManagerStrategy is not workingZF2、Oracle、SlmQueueDoctrine、ClearObjectManagerStrategy 不工作
【发布时间】:2016-03-05 03:11:42
【问题描述】:

我有一个具有以下配置的 ZF2 项目。它使用 Doctrine ORM 和 SlmQueue。由于 SlmQueue 不支持我们的命名约定和 oracle 数据库,我们自定义了 SlmQueueDoctrine。

我怀疑我的作业没有使用 ClearObjectManagerStrategy,并且在执行单个作业之前没有清除 ObjectManager。

它不反映队列启动后的数据库修改。但如果我杀死队列守护进程并重新开始,它会选择新值。

如何在执行单个作业之前实现 ClearObjectManagerStrategy 和清除 ObjectManager?

我已经尝试了很多没有运气的方法。

composer.json

{
    "repositories": [
        {
            "url": "https://github.com/pradeep-sanjaya/doctrine-extensions.git",
            "type": "git"
        }
    ],
    "require": {
        "php": ">=5.3.3",
        "zendframework/zendframework": "2.3.3",
        "doctrine/doctrine-orm-module": "0.7.*",
        "pradeep-sanjaya/doctrine-extensions": "dev-master",
        "spoonx/sxmail": "1.4.*",
        "slm/locale": "dev-master",
        "imagine/Imagine": "0.6.*",
        "tecnick.com/tcpdf": "dev-master",
        "slm/queue": "0.4.*",
        "slm/queue-doctrine": "0.4.*"
    }
}

config/autoload/slm_queue.local.php

<?php
return array(
    'slm_queue' => array(
        'queue_manager' => array(
            'factories' => array(
                'doctrineQueue' => 'SlmQueueDoctrine\Factory\DoctrineQueueFactory'
            ),
        ),
        'job_manager' => array(
            'factories' => array(
                'Report\Job\Rank' => 'Report\Job\RankFactory',
            ),
            'shared' => array(
                'Report\Job\Rank' => false
            ),
        ),
        'queues' => array(
            'doctrineQueue' => array(
                'table_name' => 'IOQUEUE'
            )
        )
    )
);
?>

module/Report/src/Report/Job/Rank.php

<?php
namespace Report\Job;

use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use DoctrineModule\Persistence\ProvidesObjectManager as ProvidesObjectManagerTrait;
use SlmQueue\Job\AbstractJob;

use Application\Entity\Report;

use Application\Log\LoggerAwareInterface;
use Application\Log\LoggerAwareTrait;

use Application\Service\ReportService;

class Rank extends AbstractJob implements ObjectManagerAwareInterface, LoggerAwareInterface
{
    use LoggerAwareTrait;
    use ProvidesObjectManagerTrait;

    /**
     * @var ReportService
     */
    protected $reportService;

    /**
     * @var array
     */
    protected $reportId = array();

    public function setReportService(ReportService $reportService)
    {
        $this->reportService = $reportService;
    }

    /**
     * Execute the job
     *
     * @return void
     */
    public function execute()
    {
        //clear object manager does not work
        //$om = $this->getObjectManager();
        //$om->clear();

        $content = $this->getContent();
        $this->setReportId($content['reportId']);

        if (!empty($this->reportId)) {
            try {
                if (is_array($this->reportId)) {
                    foreach ($this->reportId as $reportId) {
                        $this->updateRank($reportId);
                    }
                    unset($reportId);
                } else {
                    $this->updateRank($this->reportId);
                }
            } catch (\Exception $exception) {
                echo "Exception message is {$exception->getMessage()} \n";
            }
        }
    }

    private function updateRank($reportId)
    {
        /* @var $report Report */
        $report = $this->reportService->getReport($reportId);
        $this->logInfo(print_r($report, true)); // this always return older db values, the values before it start queue deamon

        if (!$report instanceof Report) {
            return;
        }

        if (empty($rankData)) {
            return;
        }

        //more codes, application related logics

        $this->reportService->updateReportEntity($report);
    }

    private function setReportId($reportId)
    {
        if (is_numeric($reportId)) {
            $this->reportId = array($reportId);
        } elseif (is_array($reportId)) {
            $this->reportId = $reportId;
        } else {
            throw new \Exception('Expects reportId as int or array');
        }
    }
}

【问题讨论】:

  • “清除对象管理器不起作用”是什么意思?你有错误吗?错误是什么? ObjectManager 没有设置吗?你在哪里注入你的ObjectManager?我没有看到构造函数...
  • 实现ObjectManagerAwareInterface并使用ProvidesObjectManager,可以从工厂注入ObjectManager
  • 带有“清除对象管理器不起作用”的注释行意味着它不会刷新对象管理器和当前事务

标签: php oracle zend-framework2 doctrine queue


【解决方案1】:

如果您的意思是它不完全清楚,那么显然this is not a bug,但预期的行为。

您可以检查 the documentation chapter 7.5. 以了解调用 clear 方法时的行为:

当 EntityManager#clear() 被调用时,当前由 EntityManager 实例管理的所有实体都将被分离。

your comment中,您说“它不会刷新对象管理器和当前事务”。这不是您可以通过调用 clear 进行的操作。根据文档,分离会导致以下操作:

分离操作的语义,应用于实体 X 如下:

  • 如果 X 是托管实体,则分离操作会导致它被分离。如果从 X 到这些其他实体的关系映射为 cascade=DETACH 或 cascade=ALL(请参阅“传递持久性”),则分离操作级联到 X 引用的实体。之前引用 X 的实体将继续引用 X。
  • 如果 X 是一个新的或分离的实体,它会被分离操作忽略。
  • 如果 X 是已删除的实体,则分离操作将级联到 X 引用的实体,如果从 X 到这些其他实体的关系映射为 cascade=DETACH 或 cascade=ALL(请参阅“传递持久性”)。之前引用 X 的实体将继续引用 X。

【讨论】:

  • 我的预期行为是在执行单个作业之前清除 ObjectManager。所以我会在运行作业之前从我的表中获取更新的结果。
猜你喜欢
  • 2016-04-26
  • 1970-01-01
  • 1970-01-01
  • 2013-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多