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

Play Framework 2.3 How to add unique constraint to sample application

鉴于 Play Framework 2.3 Computer Database sample application,我想练习在属性上添加唯一约束。假设我希望 Computer class 的 name 属性是唯一的。我试图通过向 Computer.java:

添加一个 validate() 函数(和一个 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 中的唯一性?

谢谢!

更新:见

我最终使用了 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:以下每个答案都是可能的解决方案

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

到"create a uniqueness constraint in the database"可以使用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;

    ...
  }

希望对您有所帮助!

您需要从唯一检查中排除当前实体,即像这样:

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 

P.S. ne() 表达式代表 不等于 当然,这种方法假定您name 字段是 Required

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

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

另一件事是您可以简化模型,即不需要 public 字段的吸气剂。