无限验证循环

时间:2013-10-14 19:42:40

标签: spring-roo spring-validator

我的Roo模型有验证器。

当发现错误(返回false)时,它按预期工作。

然而,当它成功时,控制器进入无限循环,产生StackOverflowError

at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:387)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:351)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:303)
at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:133)
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:136)
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:94)
at org.hibernate.action.internal.EntityInsertAction.preInsert(EntityInsertAction.java:181)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:81)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:377)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:369)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:286)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:339)
at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:62)
at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1205)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1262)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:283)
at com.foo.domain.validate.UniqueNameValidator.isValid(UniqueNameValidator.java:30)
at com.foo.domain.validate.UniqueNameValidator.isValid(UniqueNameValidator.java:1)
at org.hibernate.validator.internal.engine.ConstraintTree.validateSingleConstraint(ConstraintTree.java:308)
at org.hibernate.validator.internal.engine.ConstraintTree.validateConstraints(ConstraintTree.java:180)
at org.hibernate.validator.internal.engine.ConstraintTree.validateConstraints(ConstraintTree.java:124)
at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:86)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:442)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:387)

请注意,第一行和最后一行是相同的。在堆栈溢出发生之前,此堆栈跟踪会重复多次。

我的UniqueNameValidator如下所示:

public class UniqueNameValidator implements ConstraintValidator<UniqueFoo, Foo> {
  public boolean isValid(Foo value, ConstraintValidatorContext context) {
    TypedQuery<Long> q = ... // checks several conditions with other models in actual code
    return q.getSingleResult() == 0;
  }
}

我的Roo MVC控制器如下所示:

@RequestMapping(method = RequestMethod.POST, produces = "text/html")
public String create(@Valid Foo foo,
                     BindingResult bindingResult,
                     Model uiModel,
                     HttpServletRequest httpServletRequest) {
    if (bindingResult.hasErrors()) {
        populateCreateForm(uiModel, foo);
        return "foos/create";
    }
    uiModel.asMap().clear();

    foo.persist();

    return Session.getStoredURI("/" + encodeUrlPathSegment(foo.getId().toString(), httpServletRequest));
}

我的模型看起来像这样:

@RooJavaBean
@RooJpaActiveRecord
@UniqueName
public class Foo {
  @NotNull
  private String parentName;
  ...
}

我做错了什么?

1 个答案:

答案 0 :(得分:1)

UniqueNameValidator中的查询导致递归验证。

TypedQuery<Long> q = ... 
return q.getSingleResult() == 0;

需要:

TypedQuery<Long> q = ...
q.setFlushMode(FlushModeType.COMMIT);
return q.getSingleResult() == 0;