4

我有一个这样的地址实体:

@Entity
public class Address implements java.io.Serializable {
    @Id @GeneratedValue(strategy = IDENTITY)
    private Long id;

    @Size(max = 100)
    private String street;

    @Size(max = 15)
    private String nr;

    @Field
    @Size(min = 1, max = 20) @NotBlank
    private String city;
}

这是其他几个实体的一部分。对于这样一个实体,地址是可选的。我有一个视图,我们的用户可以通过几个表单输入来编辑整个实体,包括几个地址字段。

为了能够编辑地址,我使用空地址实体初始化父实体。

Address现在的问题是:当所有地址字段都为空时,我不想在实体上保留一个。Address为此,如果(且仅当)的所有字段为空时,我需要跳过实体的验证。我该如何以最优雅的方式做到这一点?

我目前正在做的是完全跳过 bean 验证和<o:validateBean disabled="true" />提交按钮,将地址设置为null如果它是空的。但这听起来像是一个彻底的黑客攻击,因为它在所有情况下都禁用了所有验证。我怎样才能做得更好?

4

2 回答 2

6

您可以在(and )的disabled属性中使用 EL。您可以使用 EL 检查是否已填写任何这些字段。您可以使用属性来引用 EL 中的组件。您可以通过检查与组件的客户端 ID 关联的请求参数的值来检查字段是否已填充。<f:validateBean><o:validateBean>binding

#{addressIsEmpty}然后,要在评估时禁用这些字段true的 bean 验证,使用起来更容易<f:validateBean><o:validateBean>因为前者可用于包装多个输入组件。

所以,总而言之,这应该做:

<c:set var="addressIsEmpty" value="#{empty param[street.clientId] and empty param[nr.clientId] and empty param[city.clientId]}" />

<f:validateBean disabled="#{addressIsEmpty}">
    <h:inputText binding="#{street}" value="#{bean.address.street}" />
    <h:inputText binding="#{nr}" value="#{bean.address.nr}" />
    <h:inputText binding="#{city}" value="#{bean.address.city}" />
</f:validateBean>

只有当<o:validateBean>您打算在每个输入或每个命令的基础上控制它时,它才更容易使用。

于 2013-07-06T13:50:44.997 回答
0

多个字段的交叉验证可能是一个棘手的问题。但是在这种情况下,首先困扰您的不是验证本身,而是在您持久化实体之前在您的 bean 中的某些条件下使某些实例无效的可能性。

最直接的方法是在您的视图中标记与Address实体关联的所有字段,required="false"而不关心正在填写的字段(或者只是省略它,因为它是默认值)并在您的操作中对占位符进行所有检查和修改方法,就在调用 EJB 服务之前。像这样:

public String save() {
    //do some checks
    if((entity.getAddress().getStreet() == null) && ...) {
        //assign address to null
        entity.setAddress(null);
    }
    entityService.persist(entity);
    return "success";
}
于 2013-07-05T19:21:00.923 回答