Play Framework 2.3如何为示例应用程序添加唯一约束

时间:2015-03-06 19:21:30

标签: forms playframework playframework-2.3

鉴于Play Framework 2.3 Computer Database sample application,我想练习在属性上添加唯一约束。假设我希望name类的Computer属性是唯一的。我试图通过向validate()添加Computer.java函数(和getter)来实现此目的:

public List<ValidationError> validate() {

    List<ValidationError> errors = new ArrayList<ValidationError>();

    if(Computer.find.where().eq("name", getName()).findRowCount() != 0){
        errors.add(new ValidationError("name", "Name must be unique. That value is already taken."));
    }

    return errors;
}

public String getName() {
    return name;
}

此检查在数据库中创建新记录时有效,但是,当您更新计算机对象但不更改名称时,现在会导致验证错误。有没有办法添加uniqueness constraint, similar to Rails?如何在Play中验证唯一性?

谢谢!

更新:请参阅answer by davide

我最终使用了javax.persistence API中的@Column(unique = true)约束。这不会在Play表单中生成错误;相反,它会抛出一个PersistenceException。因此我不得不添加更改我的控制器以实现我想要的行为。 create()update()操作都需要像这样的try / catch:

 try {
     computerForm.get().save();
 } catch (PersistenceException pe) {
     flash("error", "Please correct errors below.");
     formData.reject("name", "Name conflict. Please choose a different name.");
     return badRequest(createForm.render(computerForm));
 }

更新2 :以下每个答案都是可能的解决方案

2 个答案:

答案 0 :(得分:2)

我不确定这是否能回答你的问题,因为我不熟悉Ruby语法。

要“在数据库中创建唯一性约束”,您可以使用javax persistence API。 Ebean也会认识到这一点。

要拥有涉及单个字段的普通唯一性约束,您可以使用@Column annotation

  @Entity
  public class Computer extends Model {
    ...

    @Column(unique = true)
    public String name;

    ...
  }

如果您需要某些字段组合是唯一的,请使用 @Table annotation

  @Table(
        uniqueConstraints=
            @UniqueConstraint(columnNames={"name", "brand"})
    )
  @Entity
  public class Computer extends Model {
    ...

    public String name;
    public String brand;

    ...
  }

我希望它有所帮助!

答案 1 :(得分:2)

您需要从唯一检查中排除当前实体,例如:

if(Computer.find.where().eq("name", getName()).ne("id", getId()).findRowCount() != 0){
     errors.add(new ValidationError("name", "Name must be unique."));
}

它将在更新期间为您提供SQL查询:

select count(*) from computer t0 where t0.name = 'Foo' and t0.id <> 123 

这在创作期间:

select count(*) from computer t0 where t0.name = 'Foo' and t0.id is not null 

PS ne()表达式代表 Not Equal To ,当然这种方法假定您的name字段为Required < / p>

修改:我向您发送了带有工作解决方案的拉取请求,您只需在editForm中添加隐藏字段,如:

<input name="id" type="hidden" value='@computerForm("id").value'/>

其他方面是您可以简化模型,即不需要公共字段的getter。