I used to think that it doesn't really matter where to put validation logic in layered application ( Controller or Service ), but recently was developing Services that require transactions ( using spring @Transactional
). Spring creates proxies using aspects and this is how spring code looks like:
org.springframework.transaction.interceptor.TransactionAspectSupport
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
commitTransactionAfterReturning(txInfo);
return retVal;
}
So from what I see here spring opens transaction first and then executes code. Taking into account that validation may fail and DB call will not be required at all does it mean that putting validation logic to service layer will create additional load on Database e.g. application will open/rollback transactions without any reasons for it? ( rollbacks, since validation usually throws some validation exception ).