如何使用Doctrine和Symfony事务进行安全测试并设置?

时间:2013-08-16 17:43:39

标签: symfony doctrine-orm doctrine

我想了解如何使用Doctrine和Symfony进行安全的“测试和设置”操作。

我正在建立会议安排系统。我有一个名为

的实体

MeetingTime,老师和学生

除其他事项外,MeetingTime与学生之间的多对一关系与教师之间存在多对一的关系。

我想强制说,只有当正确的当前为null时,才能保存meetingTime的student属性。即,一名学生不应该覆盖另一名学生。第一个预订时间的学生获胜。似乎交易会这样做。

我这样做:

  $saved = true;

  try
  {
    $em->transactional(function($em) use($mtId, $student) {
      $mt = $em->getRepository('MyBundle:MeetingTime')->find($mtId);
      if (is_null($mt->getStudent()))
      {
        $mt->setStudent($student);
        $em->persist($mt);
      }
      else
      {
        throw new Exception();
      }
    });
  }
  catch(Exception $e)
  {
    $saved = false;
  }

  if (!$saved)
  {
// flash "Sorry,, somebody else just grabbed that time".         
  }

我的用户界面将通过在页面上显示“预订此时间”按钮来处理大部分内容,如果该时间已经完成,但当然如果有两个人同时执行此操作,则数据库具有最终决定权。

这似乎有效,但这是正确的方法吗?交易安全吗?

我首先使用额外的“预订”实体实现了它,其中一对一到MeetingTime,多对一的学生和MeetingTime的唯一约束。这项工作没有问题,但将Student作为MeetingTime的财产更好,因为我还希望MeetingTime对学生和教师有一个独特的约束,因为学生只能与老师预约一次会议。

我知道我应该创建自己的Exception类,以便我知道异常的类型。如果已经设置了正确的学生,我也应该让它感到高兴。

如果重要,数据库是PostgreSQL。我确信这可以通过触发器非常有效地完成但是...这是一个我没有进入的整个世界,并且保持这个数据库不可知是很好的。

由于

2 个答案:

答案 0 :(得分:0)

交易在这里没有帮助。所有它确保冲洗成功。它没有锁定任何东西。

请仔细阅读:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/transactions-and-concurrency.html

您可能希望使用乐观锁定,只需要在表格中添加版本号并使用@Version标记标记它。而且中提琴!虽然您需要准备好在刷新时捕获可能的异常,但不会出现并发问题。

考虑将空检查放在$ mt-> setStudent中,以便它始终发生。

答案 1 :(得分:0)

让存储库查找具有ID和null学生的MeetingTime实体。如果找到一个,那么你可以设置学生。否则告诉学生他们运气不好。

如果你还没有,你可能必须为此创建自己的存储库类。

除非你有很多学生同时预订,否则我怀疑这是一个并发问题。

Doctrine也有一个悲观的锁定选项,但有一些警告:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/transactions-and-concurrency.html#pessimistic-locking