验证:保存前检查唯一性

时间:2011-09-09 07:19:18

标签: playframework

我正在使用Play Framework开发一个Web应用程序。我的应用程序有一个User类,后者又有一个用户名和一个电子邮件属性。很标准的东西。然而...

当新用户通过表单(注册,html)注册时,我想检查用户名和密码是否唯一,如果没有,则将其重定向回表单并在那里显示消息。

我已经想过一些解决方案,其中没有一个特别优雅,在我看来,必须有一种简单的方法来检查用户名/电子邮件在数据库中是否是唯一的,而不会对表本身施加约束(导致插入重复值时的运行时错误)。

所以...有人遇到同样的问题吗?你是怎么解决的?

3 个答案:

答案 0 :(得分:2)

我在调度系统中做了类似的事情,以防止同一个人的重叠转移。在模型中,它使用@PrePersist方法查询数据库,并在发现任何可能发生冲突的事件时抛出自定义异常。

然后在控制器中我捕获异常(保存对象时将抛出异常)并重定向回到表单。

在模型中:

@PrePersist
public void prepareToInsert() {
    List<AgentShift> conflicts = find("agent=?1 and (start_time between ?2 and ?3 or end_time between ?2 and ?3)",
        agent,
        sql_datetime_formatter.print(scheduled.getStart()),
        sql_datetime_formatter.print(scheduled.getEnd())).fetch();
    if (!conflicts.isEmpty()) {
        throw new SchedulingException("New shift for " + agent +
            " overlaps existing shift which goes from " +
            sql_datetime_formatter.print(conflicts.get(0).scheduled.getStart()) + " to " +
            sql_datetime_formatter.print(conflicts.get(0).scheduled.getEnd()), conflicts);
    }

}

在控制器中:

public static void create(@Valid AgentShift object) {
    ...
    try {
        object._save();
        ...
    }
    catch (SchedulingException e) {
        flash.error("conflict with existing shift", e.getConflicts());
        redirect(request.controller + ".blank", object._key());
    }
}

答案 1 :(得分:1)

您必须使用数据库约束 - 并适当地处理异常,或使用锁定(这可能会牺牲性能)。如果您尝试进行最后一分钟检查,您将永远不会知道另一个请求是否在检查和提交之间隐藏了用户名。

虽然不常见,但可能会发生(想象一下网络很慢而且用户提交了很多次)。恕我直言,你最好只是正确处理问题,而不是希望不可能永远不会发生。

如果你愿意,我可以用代码详细说明。虽然听起来你可能已经知道如何去做(但只是寻找更优雅的解决方案)。

答案 2 :(得分:0)

我写了一篇UniqueCheck-Valitdation。您可以在此处找到有关它的信息https://play.lighthouseapp.com/projects/57987/tickets/370 您可以在http://bazaar.launchpad.net/~opensource21/+junk/permsec/files/head:/samples-and-tests/uniquetest/?file_id=psec-20110808104818-k8u827kllt5n62iq-1

找到支票的测试

我建议在数据库中定义另外一个唯一约束。