in grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormInstanceApi.groovy [99:170]
D save(D target, Map arguments) {
PersistentEntity domainClass = persistentEntity
runDeferredBinding()
boolean shouldFlush = shouldFlush(arguments)
boolean shouldValidate = shouldValidate(arguments, persistentEntity)
HibernateRuntimeUtils.autoAssociateBidirectionalOneToOnes(domainClass, target)
boolean deepValidate = true
if (arguments?.containsKey(ARGUMENT_DEEP_VALIDATE)) {
deepValidate = ClassUtils.getBooleanFromMap(ARGUMENT_DEEP_VALIDATE, arguments)
}
if (shouldValidate) {
Validator validator = datastore.mappingContext.getEntityValidator(domainClass)
Errors errors = HibernateRuntimeUtils.setupErrorsProperty(target)
if (validator) {
datastore.applicationEventPublisher?.publishEvent new ValidationEvent(datastore, target)
if (validator instanceof CascadingValidator) {
((CascadingValidator)validator).validate target, errors, deepValidate
} else if (validator instanceof org.grails.datastore.gorm.validation.CascadingValidator) {
((org.grails.datastore.gorm.validation.CascadingValidator) validator).validate target, errors, deepValidate
} else {
validator.validate target, errors
}
if (errors.hasErrors()) {
handleValidationError(domainClass,target,errors)
if (shouldFail(arguments)) {
throw validationException.newInstance("Validation Error(s) occurred during save()", errors)
}
return null
}
setObjectToReadWrite(target)
}
}
// this piece of code will retrieve a persistent instant
// of a domain class property is only the id is set thus
// relieving this burden off the developer
autoRetrieveAssociations datastore, domainClass, target
// Once we get here we've either validated this object or skipped validation, either way
// we don't need to validate again for the rest of this save.
GormValidateable validateable = (GormValidateable) target
validateable.skipValidation(true)
try {
if (shouldInsert(arguments)) {
return performInsert(target, shouldFlush)
}
else if(shouldMerge(arguments)) {
return performMerge(target, shouldFlush)
}
else {
if (target instanceof DirtyCheckable && markDirty) {
target.markDirty()
}
return performSave(target, shouldFlush)
}
} finally {
// After save, we have to make sure this entity is setup to validate again. It's possible it will
// be validated again if this save didn't flush, but without checking it's dirty state we can't really
// know for sure that it hasn't changed and need to err on the side of caution.
validateable.skipValidation(false)
}
}