我使用Symfony完整堆栈构建了一个处理XLSX文件的cli应用程序。但是,更新数据库记录中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();是单身人士吗?
答案 0 :(得分:1)
是的,默认情况下,symfony2服务的工作方式与singleton类似,您可以阅读:
http://symfony.com/doc/2.6/cookbook/service_container/scopes.html
了解范围¶
服务范围控制服务实例的时长 容器使用的。 Dependency Injection组件提供了两个 通用范围:
container(默认值):每次使用相同的实例 从这个容器请求它。 prototype:创建一个新实例 每次您请求服务
首先,如果你的'file'实体是从entityManager加载的,你就不能使用persist方法。 在刷新之前第二个转储'文件'实体并检查您尝试保存的内容。 您还可以在UnitOfWork上检查实体状态示例:
$unitOfWork = $entityManager->getUnitOfWork();
foreach ($unitOfWork->getScheduledEntityInsertions() as $entity) {
#for insert
}
foreach ($unitOfWork->getScheduledEntityUpdates() as $entity) {
# for update
}
应用于实体X的持久操作的语义如下 如下:
如果X是一个新实体,它就会被管理。将输入实体X. 作为刷新操作的结果进入数据库。如果X是 预先存在的托管实体,由persist操作忽略。 但是,持久化操作会级联到引用的实体 X,如果映射了从X到这些其他实体的关系 cascade = PERSIST或cascade = ALL(参见“传递持久性”)。如果X是 一个被删除的实体,它就会被管理。如果X是一个分离的实体,那么 在flush上会抛出异常。
我以为你是在课堂上映射实体,但你不是,我无法理解你使用'DetectedType'的关系。 如果您在某处调用'clear'方法或者如果您对关系拥有方存在问题,则可能会出现此问题,请阅读以下内容: