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

如何使用条令和Symfony事务进行安全测试和设置?,symfony,doctrine-orm,doctrine,Symfony,Doctrine Orm,Doctrine,我想了解如何使用条令和符号进行安全的“测试和设置”操作 我正在建立一个会议安排系统。我有一个名字叫 会议时间、老师和学生 除其他外,会议时间与学生和教师之间存在可取消的多对一关系 我想强制执行meetingTime的student属性只能在当前为null时保存。i、 例如,一个学生不能覆盖另一个学生。第一个预定时间的学生获胜。似乎一笔交易就能做到这一点 我正在这样做: $saved = true; try { $em->transactional(function($

我想了解如何使用条令和符号进行安全的“测试和设置”操作

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

会议时间、老师和学生

除其他外,会议时间与学生和教师之间存在可取消的多对一关系

我想强制执行meetingTime的student属性只能在当前为null时保存。i、 例如,一个学生不能覆盖另一个学生。第一个预定时间的学生获胜。似乎一笔交易就能做到这一点

我正在这样做:

  $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".         
  }
我的用户界面将通过在页面上不显示“这次预订”按钮来解决大部分问题,如果这段时间被占用,当然,如果两个人同时预订,数据库有最终决定权

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

我首先通过一个额外的“预订”实体来实现它,该实体对会议时间有一对一的限制,对学生有多对一的限制,并且对会议时间有唯一的限制。这很好,但将学生作为会议时间的一个属性更好,因为我还希望会议时间对学生和老师有一个独特的约束,因为学生只能与老师预约一次会议

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

如果有关系,数据库是PostgreSQL。我相信这可以用触发器非常有效地完成,但是。。。这是一个我还没有进入过的世界,保持db不可知是件好事


谢谢

交易在这里没有帮助。它所做的一切都确保了刷新成功。它不会锁定任何东西

请在此通读:

您可能希望使用乐观锁定,它只需要向表中添加一个版本号,并用@version标记对其进行标记。还有维奥拉!没有更多的并发性问题,尽管您确实需要准备在刷新时捕获可能的异常


并考虑将空校验放入$MT-> SETPULL中,这样总是发生。

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

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

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


信条也有一个悲观锁定选项,但有很多警告:

只是出于好奇,你为什么拒绝乐观锁定方法?添加单个版本属性对于实际的并发解决方案来说似乎是一个很小的代价。我不是一个乐观的人。:-)事实上,这不是一个真正的锁,它只是一个不同的比赛条件。同样的问题,不同的专栏。它很有帮助地抛出了一个异常,但它必须在写入之前进行另一次读取,这可能会通过减慢速度而增加并发性问题。而且,正如tetranz所说,很难测试。悲观锁是最好的,但需要小心实现。否。这是一把锁。乐观锁定背后的诀窍是使用类似于:“UPDATE meetingTime SET student='Paul',其中version=27;”如果版本已更改,则不会进行更新并引发异常。在更新操作期间,数据库始终锁定表。但这都是内在的。不需要额外的查询。易于测试。“更新会议时间设置student='Paul',version=version+1,其中version=27;”谢谢。我应该知道:)它工作得很好。测试起来很棘手,但我使用两个浏览器进行了测试,并为一个用户临时插入了一些sleep()时间。基于浏览器的手动测试总是不确定的。如果几个月后调整代码会发生什么?要再次设置两个浏览器吗?在理想的世界里,你应该能够在每次做出改变时启动一系列测试。是的,我知道你是对的。我将很快研究自动化测试。