douhuang2673 2015-05-18 11:36
浏览 54
已采纳

一组实体未更新(Symfony2&Doctrine)

I have a problem with this code:

$elements = $em
    ->getRepository('AppBundle:MyElementsEntity')
    ->findByLinkType($linkType); // This returns SEVEN elements

foreach ($elements as $e) {
    $beginDate = $e->getBeginDate();
    $beginDate->setTime($begin->format('H'), $begin->format('i'));
    $endDate = $e->getEndDate();
    $endDate->setTime($end->format('H'), $end->format('i'));

    $e->setEndDate($endDate);
    $e->setBeginDate($beginDate);

    $em->persist($e);
    $em->flush();
}

As you can see, it fetches some elements from the database, changes the time from the beginDate and endDate fields ($begin and $end are DateTime objects), and tries to update the database.

The code doesn't throw any exception, but it doesn't work. When I look at Symfony2's log (app/logs/dev.log), there are the SQL statements to fetch the data, alter sessions, etc, but there isn't any update statement.

And I have another function, that only updates one element each time, and this is working correctly.

What I'm doing wrong? Why I can batch-update the previous selected elements? I'm missing something important?

** UPDATE **

I've done some modifications to the code, but it still doesn't update the entities to the database:

  • I've removed the $em->persist($e) call.
  • I've moved the $em->flush() call to outside the foreach loop.
  • I've removed the transactional code (beginTransaction(), commit() and rollback() calls)

But the problem is still the same: Doctrine doesn't send any UPDATE statement to the server (FYI, is an Oracle 11g).

  • 写回答

2条回答 默认 最新

  • douxia2053 2015-05-19 06:30
    关注

    Thanks to all the people for your help. Finally, I've found the problem.

    The problem is with the way Doctrine looks if an entity is dirty or not. He only looks for changes in the scalar fields (strings, numbers, etc), but not in the fields that are objects (another entities, DateTime objects, etc).

    In the above fragment of code I was only modifying the content of the DateTime objects ($e->beginDate and $e->endDate), but without creating new objects. This way, Doctrine didn't notice that there where changes in the entity. The solution to avoid this is really easy:

    foreach ($elements as $e) {
        $beginDate = clone $e->getBeginDate();
        $beginDate->setTime($begin->format('H'), $begin->format('i'));
        $endDate = clone $e->getEndDate();
        $endDate->setTime($end->format('H'), $end->format('i'));
    
        $e->setEndDate($endDate);
        $e->setBeginDate($beginDate);
    
        $em->flush();
    }
    

    Notice the clone keyword when initializing the $beginDate and $endDate temporary variables: they aren't references to the $e->beginDate and $e->endDate members, but copies of them. Then, when you assign again the new values to the entity, the objects are new, and Doctrine now knows that these entities are dirty.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 宇视监控服务器无法登录
  • ¥15 PADS Logic 原理图
  • ¥15 PADS Logic 图标
  • ¥15 电脑和power bi环境都是英文如何将日期层次结构转换成英文
  • ¥15 DruidDataSource一直closing
  • ¥20 气象站点数据求取中~
  • ¥15 如何获取APP内弹出的网址链接
  • ¥15 wifi 图标不见了 不知道怎么办 上不了网 变成小地球了
  • ¥50 STM32单片机传感器读取错误
  • ¥50 power BI 从Mysql服务器导入数据,但连接进去后显示表无数据