我有一个像这样的地址实体:
@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
。但这听起来像是完全黑客,因为它会在所有案例中禁用所有验证。我怎样才能做得更好?
答案 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";
}