Spring对JDBC异常的封装
- - 编程语言 - ITeye博客 Spring对JDBC异常的封装来自于《Expert One-on-One J2EE Design and Development》一书所持的观点. 书中指明jdbc使用单一java.lang.SQLException异常表示数据访问时发生的所有异常是一 个糟糕的设计. 在JDBC API 4.0以前的版本中,异常处理功能极其有限.
Spring对JDBC异常的封装来自于《Expert One-on-One J2EE Design and Development》一书所持的观点。书中指明jdbc使用单一java.lang.SQLException异常表示数据访问时发生的所有异常是一 个糟糕的设计。在JDBC API 4.0以前的版本中,异常处理功能极其有限。对于所有类型的错误都会笼统地抛出一个SQLException异常-根本不存在异常的详细分类,且没有相应 的层次定义。所以这时,你唯一能够得到一些有意义的信息的办法是检索和分析SQLState值。另一方面,SQLState值及其相应的含义会因不同的数 据源而有所改变;因此,要想追踪到问题的"根部"并且有效地处理异常是一件非常乏味的任务。对于早期版本jdbc异常处理方式的诟病逐渐成为了一种共识, 在jdbc4.0规范中(即集成进jdk1.6的版本)对异常部分进行了大力度的改进,而这种改进与Spring对JDBC异常的封装是一致的。
Spring认为针对数据访问中发生的不同情况设计相应的异常类型,并以一定的层次关系组织起来对于client是非常重要的,也是良好设计的一种体现。 下面是Srping中一段典型的异常封装代码,我们可以从中看出,spring对于异常包装主要是通过分析从SQLException异常中得到的 sqlErrorCodes,重新封装新异常。
// Next, look for grouped error codes. if (Arrays.binarySearch(this.sqlErrorCodes.getBadSqlGrammarCodes(), errorCode) >= 0) { logTranslation(task, sql, sqlEx, false); return new BadSqlGrammarException(task, sql, sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getInvalidResultSetAccessCodes(), errorCode) >= 0) { logTranslation(task, sql, sqlEx, false); return new InvalidResultSetAccessException(task, sql, sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getDuplicateKeyCodes(), errorCode) >= 0) { logTranslation(task, sql, sqlEx, false); return new DuplicateKeyException(buildMessage(task, sql, sqlEx), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getDataIntegrityViolationCodes(), errorCode) >= 0) { logTranslation(task, sql, sqlEx, false); return new DataIntegrityViolationException(buildMessage(task, sql, sqlEx), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getPermissionDeniedCodes(), errorCode) >= 0) { logTranslation(task, sql, sqlEx, false); return new PermissionDeniedDataAccessException(buildMessage(task, sql, sqlEx), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getDataAccessResourceFailureCodes(), errorCode) >= 0) { logTranslation(task, sql, sqlEx, false); return new DataAccessResourceFailureException(buildMessage(task, sql, sqlEx), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getTransientDataAccessResourceCodes(), errorCode) >= 0) { logTranslation(task, sql, sqlEx, false); return new TransientDataAccessResourceException(buildMessage(task, sql, sqlEx), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getCannotAcquireLockCodes(), errorCode) >= 0) { logTranslation(task, sql, sqlEx, false); return new CannotAcquireLockException(buildMessage(task, sql, sqlEx), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getDeadlockLoserCodes(), errorCode) >= 0) { logTranslation(task, sql, sqlEx, false); return new DeadlockLoserDataAccessException(buildMessage(task, sql, sqlEx), sqlEx); } else if (Arrays.binarySearch(this.sqlErrorCodes.getCannotSerializeTransactionCodes(), errorCode) >= 0) { logTranslation(task, sql, sqlEx, false); return new CannotSerializeTransactionException(buildMessage(task, sql, sqlEx), sqlEx); }