Validation API: сложные проверки

Автор PremaServices - Понедельник, 24 Июнь 2013. В рубриках: Validation API, Hibernate

Аннотация уровня класса объекта

Под сложной проверкой подразумеваются случаи, когда условие накладывается не на одно свойство объекта, а сразу на несколько. В этом случае требуется описать аннотацию уровня класса с @Target(ElementType.TYPE), где реализовать все необходимое. Один такой пример проверки на уникальность объекта @Unique уже был реализован нами ранее. Рассмотрим ещё один простой случай, когда свойства объекта связаны между собой логическими отношениями.


Постановка задачи

Студенты нашей школы астрологии производят оплату за обучение, а значит нам необходимо фиксировать в базе данных каждый платеж. В Hibernate мы отражаем такой платеж специальной сущностью, причем, платеж проходит только при условии, если указано, за что конкретно оплатил студент. Это может быть оплата очередной сессии, мастер-класса или дальнейшая проплата за обучение.

package ru.premaservices.astroved.student.pojo;
...
 
@Entity
@Table(name="PAIMENT") @PaymentConstraint
public class Payment implements Comparable<Payment> {
 
	@Id @GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name="ID")
	private Integer id;
 	
	@NotNullObjectId("uid")
	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="UID")
	private Student student;
 	
	@NotNull
	@Column(name="DATE_PMNT")
	@Temporal(value=TemporalType.DATE)
	private Date paimentDate;
 	
	@Range(min=1)
	@Column(name="SUM")
	private Integer sum;
 	
	@Column(name="COURSE")
	@Enumerated(EnumType.ORDINAL)
	private Course course;
 	
	@ManyToOne(fetch=FetchType.EAGER)
	@NotFound(action=NotFoundAction.IGNORE)
	@JoinColumn(name="SESSION")
	private Session session;
 	
	@Column(name="MASTER_CLASS", length=50)
	private String masterClass;
 	
	@Lob @Basic(fetch=FetchType.EAGER)
	@Column(name="COMMENT")
	private String comment;
  
	...
	@Override
	public int compareTo(Payment that) {
		if (that == null) {
	       return -1;
	    }
		return that.getPaimentDate().compareTo(this.getPaimentDate());
	}
	
}

Здесь мы видим, что платеж связан со студентом, его осуществляющим, имеет дату и сумму не меньшую, чем 1 рубль. А далее идут три свойства: курс, мастер-класс и сессия, и каждое из них в принципе может оставаться пустым, но при этом хоть одно из них должно быть заполнено.


Аннотация

Для осуществления такой сложной проверки введем дополнительную аннотацию @PaymentConstraint.

package ru.premaservices.astroved.student.pojo.validation;
...
@Documented
@Constraint(validatedBy = {PaymentValidator.class})
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface PaymentConstraint {
	String message() default "{ru.premaservices.astroved.student.pojo.PaymentConstraint.message}";
	Class<?>[] groups() default {};
	Class<? extends Payload>[] payload() default {};
}

У этой аннотации нет никаких входных параметров, иными словами, она служит маркером, указывающим, что нужно выполнить определенные проверки над объектом Payment. И сразу зададим текст сообщения об ошибке в файле ValidationMessages.properties:

ru.premaservices.astroved.student.pojo.validation.PaymentConstraint.message=Нужно указать номер курса, или сессию, или мастер-класс


Класс валидации

package ru.premaservices.astroved.student.pojo.validation;
...
public class PaymentValidator implements ConstraintValidator<PaymentConstraint, Payment> {
 
	@Override
	public void initialize(PaymentConstraint arg0) {		
	}
 
	@Override
	public boolean isValid(Payment payment, ConstraintValidatorContext arg1) {
		if (payment.getCourse().compareTo(Course.NONE) == 0 && (payment.getSession() == null || payment.getSession().getId() == null || payment.getSession().getId() == 0) && !CommonUtil.isNotBlank(payment.getMasterClass())) {
			return false;
		}
		else return true;		
	}
 
}

 В контроллере Spring запускаем через параметр:
@ModelAttribute("payment") @Valid Payment p

  • 0.0/5 оценка (0 голосов)
  • Тэги: Validation API, аннотация, проверка данных

Об авторе

Комментарии (0)

Оставить комментарий

Вы комментируете как Гость.