0

我已经用 Symfony 全栈构建了一个 cli 应用程序来处理 XLSX 文件。但是,在 2 个不同点更新数据库记录中的信息会导致记录被复制而不是更新。

应用程序的最简单分解是:

命令

class AppProcessFilesCommand extends ContainerAwareCommand
{

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $em = $this-setContainer>getContainer()->get('doctrine')->getManager();
        $file = $em->getRepository( 'AppBundle:FileToSync' )->findBy(
                ['processed' => null],
                ['modified' => 'ASC']
            );
            if (sizeof($file) > 0) {
                $file = $file[0];

                foreach (ProcessorFactory::getAvailableProcessors() as $processor) {
                    $start = microtime( true );                        
                    if (ProcessorFactory::getInstance( $processor )
                                        ->setOutput( $output )
                                        ->setContainer( $this->getContainer() )
                                        ->setDoctrine( $this->getContainer()->get( 'doctrine' ) )
                                        ->process( $file )
                    ) {
                        $processorFound = true;
                        $file->setTimeTaken( microtime( true ) - $start );
                        $file->setProcessed( new \DateTime() );
                        $em->persist($file);
                        $em->flush();
                    }
                }

处理循环

class Processor
{
    public function process($fileToSync)
    {
        $foundFiles = $this->convertToCsv($file);
        $noRows = $this->processCsvSheets($foundFiles, $fileToSync);

        $em = $this->getDoctrine()->getManager();
        $fileToSync->setDetectedTypeId($this->getMyFileTypeId());
        $fileToSync->setRowCount($noRows);
        $em->persist($fileToSync);
        $em->flush();

实体类

namespace AppBundle\Entity;


class FileToSync
{
    private $id;

    private $absolute_path;

    private $modified;

    private $processed;

    /**
     * @var int
     */
    private $detected_type_id;

    private $time_taken;

    private $row_count;

        /**
     * @var \AppBundle\Entity\DetectedType
     */
    private $DetectedType;


    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set absolutePath
     *
     * @param string $absolutePath
     *
     * @return FileToSync
     */
    public function setAbsolutePath($absolutePath)
    {
        $this->absolute_path = $absolutePath;

        return $this;
    }

    /**
     * Get absolutePath
     *
     * @return string
     */
    public function getAbsolutePath()
    {
        return $this->absolute_path;
    }

    /**
     * Set modified
     *
     * @param \DateTime $modified
     *
     * @return FileToSync
     */
    public function setModified($modified)
    {
        $this->modified = $modified;

        return $this;
    }

    /**
     * Get modified
     *
     * @return \DateTime
     */
    public function getModified()
    {
        return $this->modified;
    }

    /**
     * Set detectedTypeId
     *
     * @param \integer $detectedTypeId
     *
     * @return FileToSync
     */
    public function setDetectedTypeId($detectedTypeId)
    {
        $this->detected_type_id = $detectedTypeId;

        return $this;
    }

    /**
     * Get detectedTypeId
     *
     * @return \integer
     */
    public function getDetectedTypeId()
    {
        return $this->detected_type_id;
    }

    /**
     * Set processed
     *
     * @param \datetime $processed
     *
     * @return FileToSync
     */
    public function setProcessed(\datetime $processed)
    {
        $this->processed = $processed;

        return $this;
    }

    /**
     * Get processed
     *
     * @return \datetime
     */
    public function getProcessed()
    {
        return $this->processed;
    }

    /**
     * Set detectedType
     *
     * @param \AppBundle\Entity\DetectedType $detectedType
     *
     * @return FileToSync
     */
    public function setDetectedType(\AppBundle\Entity\DetectedType $detectedType = null)
    {
        $this->DetectedType = $detectedType;

        return $this;
    }

    /**
     * Get detectedType
     *
     * @return \AppBundle\Entity\DetectedType
     */
    public function getDetectedType()
    {
        return $this->DetectedType;
    }

    /**
     * Set timeTaken
     *
     * @param string $timeTaken
     *
     * @return FileToSync
     */
    public function setTimeTaken($timeTaken)
    {
        $this->time_taken = $timeTaken;

        return $this;
    }

    /**
     * Get timeTaken
     *
     * @return string
     */
    public function getTimeTaken()
    {
        return $this->time_taken;
    }

    /**
     * Set rowCount
     *
     * @param integer $rowCount
     *
     * @return FileToSync
     */
    public function setRowCount($rowCount)
    {
        $this->row_count = $rowCount;

        return $this;
    }

    /**
     * Get rowCount
     *
     * @return integer
     */
    public function getRowCount()
    {
        return $this->row_count;
    }
}

实体映射 (yml)

AppBundle\Entity\DetectedType:
    type: entity
    table: detected_type
    id:
        id:
            type: integer
            generator: { strategy: AUTO }
    fields:
        name:
            type: string
            length: 501

AppBundle\Entity\FileToSync:
    type: entity
    table: file_to_sync
    id:
        id:
            type: integer
            generator: { strategy: AUTO }
    manyToOne:
        DetectedType:
            targetEntity: DetectedType
            joinColumn:
                name: detected_type_id
                referencedColumnName: id
    fields:
        absolute_path:
            type: string
            length: 255
        modified:
            type: datetime
        detected_type_id:
            type: integer
            nullable: true
        processed:
            type: datetime
            nullable: true
        time_taken:
            type: decimal
            precision: 11
            scale: 6
            nullable: true
        row_count:
            type: integer
            nullable: true


AppBundle\Entity\Transaction:
    type: entity
    table: transaction
    id:
        id:
            type: integer
            generator: { strategy: AUTO }
    uniqueConstraints:
        txnId:
          columns: [ txn_id ]
    manyToOne:
        FileToSync:
            targetEntity: FileToSync
            joinColumn:
                name: file_id
                referencedColumnName: id
    fields:
        txnDate:
            type: datetime
        file_id:
            type: integer

在处理循环中,$fileToSync 没有更新,而是插入了一条新记录。然后在命令中更新。

我的工作假设是 $this->getContainer()->get('doctrine')->getManager(); 作为单身人士工作?

4

1 回答 1

1

是的,默认情况下 symfony2 服务像单例一样工作,你可以阅读以下内容:

http://symfony.com/doc/2.6/cookbook/service_container/scopes.html

了解作用域¶

服务的范围控制容器使用服务实例的时间。依赖注入组件提供了两个通用范围:

容器(默认):每次从该容器请求时使用相同的实例。原型:每次请求服务时都会创建一个新实例

首先,如果您的“文件”实体是从 entityManager 加载的,则不能使用持久方法。在刷新之前第二次转储“文件”实体并检查您尝试保存的内容。您还可以在 UnitOfWork 此处查看实体状态示例:

$unitOfWork = $entityManager->getUnitOfWork();

foreach ($unitOfWork->getScheduledEntityInsertions() as $entity) {
   #for insert
}

foreach ($unitOfWork->getScheduledEntityUpdates() as $entity) {
    # for update
}

应用于实体 X 的持久操作的语义如下:

如果 X 是一个新实体,它就会成为托管实体。作为刷新操作的结果,实体 X 将被输入到数据库中。如果 X 是预先存在的托管实体,则持久操作将忽略它。但是,如果从 X 到这些其他实体的关系映射为 cascade=PERSIST 或 cascade=ALL,则持久操作将级联到 X 引用的实体(请参阅“传递持久性”)。如果 X 是一个被移除的实体,它就会变成托管的。如果 X 是分离的实体,则刷新时将引发异常。

我以为你是在课堂上映射实体,但你不是,我无法理解你使用“DetectedType”的关系。如果您在某处调用 'clear' 方法或者如果您对关系拥有方有问题,则可能会发生此问题,请阅读以下内容:

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/unitofwork-associations.html

于 2016-10-25T09:16:39.883 回答