2011-10-06 16 views
3

我在验证时遇到了非常特定的bean问题。 让我给你一些代码第一:在包含具有不同组接口bean的bean中进行多个验证

@Entity 
@Table(name = "customers", schema = "public", uniqueConstraints = @UniqueConstraint(columnNames = {"cus_email" })) 
public class Customers extends ModelObject implements java.io.Serializable { 

    private static final long serialVersionUID = -3197505684643025341L; 

    private long cusId; 
    private String cusEmail; 
    private String cusPassword; 
    private Addresses shippingAddress; 
    private Addresses invoiceAddress; 

    @Id 
    @Column(name = "cus_id", unique = true, nullable = false) 
    @SequenceGenerator(name = "cus_seq", sequenceName = "customers_cus_id_seq", allocationSize = 1) 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "cus_seq") 
    @NotNull 
    public long getCusId() { 
     return cusId; 
    } 

    public void setCusId(long cusId) { 
     this.cusId = cusId; 
    } 

    @NotEmpty 
    @Size(min=5, max=255) 
    @Email 
    @Column(name = "cus_email", unique = true, nullable = false, length = 255) 
    public String getCusEmail() { 
     return cusEmail; 
    } 

    public void setCusEmail(String cusEmail) { 
     this.cusEmail = cusEmail; 
    } 

    @NotNull 
    @Column(name = "cus_password", nullable = false) 
    public String getCusPassword() { 
     return cusPassword; 
    } 

    public void setCusPassword(String cusPassword) { 
     this.cusPassword = cusPassword; 
    } 

    @NotNull 
    @OneToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "cus_shipping_adr_id", nullable = false) 
    @Cascade(value = CascadeType.ALL) 
    @Valid 
    public Addresses getShippingAddress() { 
     return shippingAddress; 
    } 

    public void setShippingAddress(Addresses cusShippingAddress) { 
     this.shippingAddress = cusShippingAddress; 
    } 

    @OneToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "cus_invoice_adr_id", nullable = true) 
    @Cascade(value = CascadeType.ALL) 
    @Valid 
    public Addresses getInvoiceAddress() { 
     return invoiceAddress; 
    } 

    public void setInvoiceAddress(Addresses cusInvoiceAddress) { 
     this.invoiceAddress = cusInvoiceAddress; 
    } 
} 

正如你所看到的,我这里有两个地址字段 - 一个用于送货地址,其他发票的地址。
每种类型的地址的验证应该不同,例如,我在收货地址中不需要增值税号码,但我可能需要发票。

我使用组对发票地址和送货地址执行不同的验证,如果我对地址字段进行手动验证,则工作正常。

但现在我想验证整个客户对象的地址(如果可用)。
我试图做到这一点与下面的代码:

private void validateCustomerData() throws CustomerValidationException { 
     ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 
     Validator validator = factory.getValidator(); 
     Set<ConstraintViolation<Customers>> constraintViolations; 
     constraintViolations = validator.validate(customer, Default.class, InvoiceAddressCheck.class, ShippingAddressCheck.class); 
     if (!constraintViolations.isEmpty()) { 
      throw new CustomerValidationException(3, Message.CustomerDataException, constraintViolations); 
     } 
    } 


当然,因为它认为这是行不通的,因为这两种验证是客户对象内的地址对象的两个实例运行,所以我得到来自InvoiceAddressCheck界面的送货地址中的错误以及ShippingAddressCheck中发票地址中的错误。

这里被缩短申报地址豆:

@Entity 
@Table(name = "addresses", schema = "public") 
@TypeDef(name = "genderConverter", typeClass = GenderConverter.class) 
public class Addresses extends ModelObject implements Serializable{ 

     private static final long serialVersionUID = -1123044739678014182L; 

     private long adrId; 
     private String street; 
     private String houseNo; 
     private String zipCode; 
     private String state; 
     private String countryCode; 
     private String vatNo; 
     private Customers customersShipping; 
     private Customers customersInvoice; 

     public Addresses() {} 

     public Addresses(long adrId) { 
      super(); 
      this.adrId = adrId; 
     } 

     @Id 
     @Column(name = "adr_id", unique = true, nullable = false) 
     @SequenceGenerator(name = "adr_seq", sequenceName = "adr_id_seq", allocationSize = 1) 
     @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "adr_seq") 
     @NotNull 
     public long getAdrId() { 
      return adrId; 
     } 

     public void setAdrId(long adrId) { 
      this.adrId = adrId; 
     } 

     @NotNull 
     @Column(name = "adr_street", nullable = false) 
     public String getStreet() { 
      return street; 
     } 

     public void setStreet(String street) { 
      this.street = street; 
     } 

     @NotEmpty(groups = ShippingAddressCheck.class) 
     @Column(name = "adr_house_no") 
     public String getHouseNo() { 
      return houseNo; 
     } 


     @NotEmpty(groups = ShippingAddressCheck.class) 
     @Column(name = "adr_zip_code") 
     public String getZipCode() { 
      return zipCode; 
     } 

     public void setZipCode(String zipCode) { 
      this.zipCode = zipCode; 
     } 

     @Column(name = "adr_vat_no") 
     @NotEmpty(groups = InvoiceAddressCheck.class) 
     public String getVatNo() { 
      return vatNo; 
     } 

     public void setVatNo(String vatNo) { 
      this.vatNo = vatNo; 
     } 

     @OneToOne(fetch = FetchType.LAZY, mappedBy = "shippingAddress") 
     public Customers getCustomersShipping() { 
      return customersShipping; 
     } 

     public void setCustomersShipping(Customers customersShipping) { 
      this.customersShipping = customersShipping; 
     } 

     @OneToOne(fetch = FetchType.LAZY, mappedBy = "invoiceAddress") 
     public Customers getCustomersInvoice() { 
      return customersInvoice; 
     } 

     public void setCustomersInvoice(Customers customersInvoice) { 
      this.customersInvoice = customersInvoice; 
     } 
    } 


有什么办法来运行验证,使invoiceAddress与InvoiceAddressCheck组和shippingAddress与ShippingAddressCheck组验证验证,但是在验证Customer对象时运行?
我知道我可以为每个子对象手动执行它,但这不是这里的要点。

回答

1

现在的临时解决方案是编写发票字段的自定义验证,因此它只检查InvoiceAddressCheck。
这里是我的代码有

译注:

@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@Constraint(validatedBy = {InvoiceAddressValidator.class }) 
public @interface InvoiceAddressChecker { 
    String message() default "Invoice address incorrect."; 

    Class<?>[] groups() default {}; 

    Class<? extends Payload>[] payload() default {}; 
} 

验证:

public class InvoiceAddressValidator implements ConstraintValidator<InvoiceAddressChecker, Addresses> { 

    @Override 
    public void initialize(InvoiceAddressChecker params) { 
    } 

    @Override 
    public boolean isValid(Addresses invoiceAddress, ConstraintValidatorContext context) { 
     // invoice address is optional 
     if (invoiceAddress == null) { 
      return true; 
     } 
     ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 
     Validator validator = factory.getValidator(); 
     Set<ConstraintViolation<Addresses>> constraintViolations; 
     constraintViolations = validator.validate(invoiceAddress, Default.class, InvoiceAddressCheck.class); 
     if (constraintViolations.isEmpty()) { 
      return true; 
     } else { 
      context.disableDefaultConstraintViolation(); 
      Iterator<ConstraintViolation<Addresses>> iter = constraintViolations.iterator(); 
      while (iter.hasNext()) { 
       ConstraintViolation<Addresses> violation = iter.next(); 
       context.buildConstraintViolationWithTemplate(violation.getMessage()).addNode(
         violation.getPropertyPath().toString()).addConstraintViolation(); 
      } 
      return false; 
     } 
    } 
} 

和型号标注:

@OneToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "cus_invoice_adr_id", nullable = true) 
@Cascade(value = CascadeType.ALL) 
@InvoiceAddressChecker 
public Addresses getInvoiceAddress() { 
    return invoiceAddress; 
} 

这是不是很好的解决方案,但它能满足我的需求。 如果你找出更好的解决方案,请让我知道:)