我正在使用Play Framework开发一个Web应用程序。我的应用程序有一个User类,后者又有一个用户名和一个电子邮件属性。很标准的东西。然而...
当新用户通过表单(注册,html)注册时,我想检查用户名和密码是否唯一,如果没有,则将其重定向回表单并在那里显示消息。
我已经想过一些解决方案,其中没有一个特别优雅,在我看来,必须有一种简单的方法来检查用户名/电子邮件在数据库中是否是唯一的,而不会对表本身施加约束(导致插入重复值时的运行时错误)。
所以...有人遇到同样的问题吗?你是怎么解决的?
答案 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
找到支票的测试我建议在数据库中定义另外一个唯一约束。