My probably goes a little against the grain of what you are saying, though I've only just read your comments...
What I've done is to extend the framework to allow iBATIS to return an int for insertions calls, then created a constants file (as a HashMap) to turn returned values into entries from the properties file. As far as I'm concerned it means that I don't have to think what select statements I have to do to enforce the db design - with the added bonus of not having to run the statements in the first place as they have their own overhead. The only bad bit is how I determine the error, which is done using a regular expression. Although I feel this is maybe not the cleanest approach I do feel it will be fast, reliable, and require no additional configuration (other than to set the appropiate value in my properties file). It also means that if I discover a better way to catch the error I can change it in the extension bit I have written without updating anything else. Furthermore you could just as easily catch more errors and have a different value in your properties file for each. Beow is how my app deals with the connection: >>>>>> int errorStatus = moduleService.insertModule(module); if (errorStatus < 0) { // All error states have a negative value in constants file. String propertiesName = SqlMapDaoConstants.getErrorKey(errorStatus); ActionMessages msgs = new ActionMessages(); ActionMessage message = new ActionMessage(propertiesName); msgs.add(ActionMessages.GLOBAL_MESSAGE, message); saveMessages(request, msgs); return mapping.findForward("insertSuccess"); } // Insertion was a success // Note: Variable 'msgs' used as not to hide field: // 'org.apache.struts.actions.DispatchAction.messages' ActionMessages msgs = new ActionMessages(); ActionMessage message = new ActionMessage( "message.module.insert.success"); msgs.add(ActionMessages.GLOBAL_MESSAGE, message); saveMessages(request, msgs); return mapping.findForward("insertSuccess"); <<<<<<