Reputation: 161
How to create a validator restrictions for more fields through annotation in spring 4.* for example
@UniqueValidator
@Entity
@Table(name = "persons")
@UniqueValidator(message="Peson already exist",columns={"name","lastName"})
public class {
@Column
private String name;
@Column
private String lastName;
}
roughly speaking..
select ... from persons where name='qwerty' and lastName='asdfgh'
Upvotes: 4
Views: 6591
Reputation:
Here's one way to do it in Spring MVC and JSR 303 validation:
Create a constraint annotation:
package com.awgtek.model.validation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
/**
* The target field should be unique in the data store.
*/
@Documented
@Constraint(validatedBy = UniqueNameValidator.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface UniqueName {
/**
* @return the error message template
*/
String message() default "{com.awgtek.model.validation.UniqueName.message}";
/**
* @return the groups the constraint belongs to
*/
Class<?>[] groups() default {};
/**
* @return the payload associated to the constraint
*/
Class<? extends Payload>[] payload() default {};
/**
* @return a class an instance of which will be used to check the existence of a name.
*/
Class<? extends NameExistenceChecker> nameExistenceChecker();
}
Apply this annotation at the class level to the model class:
package com.awgtek.model;
import com.awgtek.model.validation.MyNameExistenceChecker;
import com.awgtek.model.validation.UniqueName;
import com.awgtek.model.validation.UniqueNameConstraint;
@UniqueName(groups = UniqueNameConstraint.class,
nameExistenceChecker = MyNameExistenceChecker.class)
public class ConfigurationAttribute {
private String name;
private String lastName;
// getters and setters omitted
}
The UniqueNameValidator
:
package com.awgtek.model.validation;
import com.awgtek.service.MyService;
import javax.inject.Inject;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class UniqueNameValidator implements ConstraintValidator<UniqueName, Object> {
@Inject
private NameExistenceCheckerFactory nameExistenceCheckerFactory;
private NameExistenceChecker nameExistenceChecker;
@Override
public void initialize(UniqueName constraintAnnotation) {
nameExistenceChecker = nameExistenceCheckerFactory.get(constraintAnnotation.nameExistenceChecker());
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
return !nameExistenceChecker.nameExists(value);
}
}
The UniqueNameValidator
then depends on a couple of classes:
package com.awgtek.model.validation;
import javax.inject.Inject;
import org.springframework.stereotype.Component;
@Component
public class NameExistenceCheckerFactory {
@Inject
private NamespaceNameExistenceChecker namespaceNameExistenceChecker;
@Inject
private MyNameExistenceChecker myNameExistenceChecker;
public NameExistenceChecker get(Class<? extends NameExistenceChecker> clazz) {
if (clazz.equals(MyNameExistenceChecker.class)) {
return myNameExistenceChecker;
}
throw new IllegalStateException("Unknown NameExistenceChecker");
}
}
package com.awgtek.model.validation;
public interface NameExistenceChecker {
boolean nameExists(Object objectWithName);
}
The implementation class that actually looks up whether the item exists in the database (via a service):
package com.awgtek.model.validation;
import com.awgtek.model.MyModelClass;
import com.awgtek.service.MyService;
import javax.inject.Inject;
import org.springframework.stereotype.Component;
@Component
public class AttributeNameExistenceChecker implements NameExistenceChecker {
@Inject
private MyService myService;
@Override
public boolean nameExists(Object objectWithName) {
MyModelClass myObject = (MyModelClass) objectWithName;
return myService.itemAlreadyExists(myObject.getName(), myObject.getLastName());
}
}
Upvotes: 2