According to the code in AbstractSavePersistentMethod the validate occurs before the save/flush, so if it fails and failOnError is true, the ValidationException will be thrown and no flush will occur.
if (errors.hasErrors()) {
handleValidationError(domainClass,target,errors);
boolean shouldFail = shouldFail(application, domainClass);
if (argsMap != null && argsMap.containsKey(ARGUMENT_FAIL_ON_ERROR)) {
shouldFail = GrailsClassUtils.getBooleanFromMap(ARGUMENT_FAIL_ON_ERROR, argsMap);
}
if (shouldFail) {
throw new ValidationException("Validation Error(s) occurred during save()", errors);
}
return null;
}
...
return performSave(target, shouldFlush); //here flush can happen