Hibernate ClassValidator實例
Hibernate有很多值得學習的地方,這里我們主要介紹Hibernate ClassValidator實例,包括介紹Spring MVC 控制器使用的 CreditCardValidator等方面。
創建一個Hibernate ClassValidator實例
這個類進行實例化的代價可能會很高,因此最好只對希望進行驗證的每個類來進行實例化。一種方法是創建一個實用工具類,對每個模型對象存儲一個Hibernate ClassValidator實例,如下所示:
處理驗證的實用工具類
- /**
- * Handles validations based on the Hibernate Annotations Validator framework.
- * @author Ted Bergeron
- * @version $Id: AnnotationValidator.java,v 1.5 2006/01/20 17:34:09 ted Exp $
- */
- public class AnnotationValidator {
- private static Log log = LogFactory.getLog(AnnotationValidator.class);
- // It is considered a good practice to execute these lines once and
- // cache the validator instances.
- public static final ClassValidator<Customer> CUSTOMER_VALIDATOR =
- new ClassValidator<Customer>(Customer.class);
- public static final ClassValidator<CreditCard> CREDIT_CARD_VALIDATOR =
- new ClassValidator<CreditCard>(CreditCard.class);
- private static ClassValidator<? extends BaseObject> getValidator(Class<?
- extends BaseObject> clazz) {
- if (Customer.class.equals(clazz)) {
- return CUSTOMER_VALIDATOR;
- }
- else if (CreditCard.class.equals(clazz)) {
- return CREDIT_CARD_VALIDATOR;
- }
- else {
- throw new IllegalArgumentException("Unsupported class was passed.");
- }
- }
- public static InvalidValue[] getInvalidValues(BaseObject modelObject) {
- String nullnullProperty = null;
- return getInvalidValues(modelObject, nullProperty);
- }
- public static InvalidValue[] getInvalidValues(BaseObject modelObject,
- String property) {
- Class<? extends BaseObject>clazz = modelObject.getClass();
- ClassValidator validator = getValidator(clazz);
- InvalidValue[] validationMessages;
- if (property == null) {
- validationMessages = validator.getInvalidValues(modelObject);
- }
- else {
- // only get invalid values for specified property.
- // For example, "city" applies to getCity() method.
- validationMessages = validator.getInvalidValues(modelObject, property);
- }
- return validationMessages;
- }
- }
創建了兩個Hibernate ClassValidator,一個用于 Customer,另外一個用于 CreditCard。這兩個希望進行驗證的類可以調用 getInvalidValues(BaseObject modelObject),會返回 InvalidValue[]。這則會返回一個包含模型對象實例錯誤的數組。另外,這個方法也可以通過提供一個特定的屬性名來調用,這樣做會只返回與該域有關的錯誤。
在使用 Spring MVC 和 Hibernate Validator 時,為信用卡創建一個驗證過程變得非常簡單,如下所示:
Spring MVC 控制器使用的 CreditCardValidator
- /**
- * Performs validation of a CreditCard in Spring MVC.
- *
- * @author Ted Bergeron
- * @version $Id: CreditCardValidator.java,v 1.2 2006/02/10 21:53:50 ted Exp $
- */
- public class CreditCardValidator implements Validator {
- private CreditCardService creditCardService;
- public void setCreditCardService(CreditCardService service) {
- this.creditCardService = service;
- }
- public boolean supports(Class clazz) {
- return CreditCard.class.isAssignableFrom(clazz);
- }
- public void validate(Object object, Errors errors) {
- CreditCard creditCard = (CreditCard) object;
- InvalidValue[] invalids = AnnotationValidator.getInvalidValues(creditCard);
- // Perform "expensive" validation only if no simple errors found above.
- if (invalids == null || invalids.length == 0) {
- boolean validCard = creditCardService.validateCreditCard(creditCard);
- if (!validCard) {
- errors.reject("error.creditcard.invalid");
- }
- }
- else {
- for (InvalidValue invalidValue : invalids) {
- errors.rejectValue(invalidValue.getPropertyPath(),
- null, invalidValue.getMessage());
- }
- }
- }
- }
validate() 方法只需要將 creditCard 實例傳遞給這個驗證過程,從而返回 InvalidValue 數組。如果發現了一個或多個這種簡單錯誤,那么就可以將 Hibernate 的 InvalidValue 數組轉換成 Spring 的 Errors 對象。如果用戶已經創建了這個信用卡并且沒有出現任何簡單錯誤,就可以將更加徹底的驗證委托給服務層進行。這一層可以與商業服務提供者一起對信用卡進行驗證。
現在我們已經看到這個簡單的模型層注釋是如何平衡到控制器、DAO 和 DBMS 層的驗證的。在 Hibernate Doclet 和 Commons Validator 中發現的驗證邏輯的重合現在都已經統一到模型中了。盡管這是一個非常受歡迎的改進,但是視圖層傳統上來說一直是最需要進行詳細驗證的地方。
【編輯推薦】