如果实体的所有字段都为空,我如何跳过bean验证?

时间:2013-07-05 15:18:32

标签: jsf-2 bean-validation omnifaces

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

@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的所有字段都为空。我如何以最优雅的方式做到这一点?

我目前正在做的是使用<o:validateBean disabled="true" />对提交按钮完全跳过bean验证,如果地址为空则将地址设置为null。但这听起来像是完全黑客,因为它会在所有案例中禁用所有验证。我怎样才能做得更好?

2 个答案:

答案 0 :(得分:5)

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

然后,要在#{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>更容易使用。

答案 1 :(得分: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";
}