`
sarin
  • 浏览: 1748083 次
  • 性别: Icon_minigender_1
  • 来自: 大连
博客专栏
E3b14d1f-4cc5-37dd-b820-b6af951740bc
Spring数据库访问系列...
浏览量:172828
C2083dc5-6474-39e2-993e-263652d27795
Android学习笔记
浏览量:366557
5f40a095-b33c-3e8e-8891-606fcf3b8d27
iBatis开发详解
浏览量:188312
B272a31d-e7bd-3eff-8cc4-c0624ee75fee
Objective-C学习...
浏览量:98754
社区版块
存档分类
最新评论

Spring数据库访问之异常处理

阅读更多
    使用JDBC API时,很多操作都要声明抛出java.sql.SQLException异常,通常情况下是要制定异常处理策略。而Spring的JDBC模块为我们提供了一套异常处理机制,这套异常系统的基类是DataAccessException,它是RuntimeException的一种类型,那么就不用强制去捕捉异常了,Spring的异常体系如下:

    目前为止我们还没有明确地处理Spring中JDBC模块的异常。要理解它的异常处理机制,我们来做几个测试。看下面的测试代码:
	public void insert(final Vehicle vehicle) {
		String sql = "insert into vehicle(ID,PLATE,CHASSIS,COLOR,WHEEL,SEAT) values(:id,:plate,:chassis,:color,:wheel,:seat)";
		SqlParameterSource parameterSource = new BeanPropertySqlParameterSource(
				vehicle);
		getSimpleJdbcTemplate().update(sql, parameterSource);
	}

	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext(		"classpath:org/ourpioneer/vehicle/spring/applicationContext.xml");
		VehicleDAO vehicleDAO = (VehicleDAO) ctx.getBean("vehicleDAO");
		Vehicle vehicle = new Vehicle("辽B-000000", "1A00000001", "RED", 4, 4);
		vehicle.setId(1);
			vehicleDAO.insert(vehicle);
}

    修改SQL语句,不使用自增主键的特性,并在这里设置重复的主键,那么运行程序,就会报出字段重复的异常。下面来捕捉这个异常:
		try {
			vehicleDAO.insert(vehicle);
		} catch (DataAccessException e) {
			SQLException sqle = (SQLException) e.getCause();
			System.out.println("Error code: " + sqle.getErrorCode());
			System.out.println("SQL state: " + sqle.getSQLState());
		}

    此时,我们就可以获得错误码和SQL状态(不同的数据库系统会有不同):

    关于HSQL数据库的错误码可以到org.hsqldb.Trace类中查看,只要注意运行结果会有一个负号,而类中定义的是没有负号的。这样就知道了这个错误的具体含义,比如104:唯一约束验证失败。这就是我们故意设置的重复主键问题。
    Spring的JDBC模块为我们预定义了一些错误代码,它存储在org.springframework.jdbc.support包下的sql-error-codes.xml文件中,其中描述HSQL的内容为:
	<bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes">
		<property name="databaseProductName">
			<value>HSQL Database Engine</value>
		</property>
		<property name="badSqlGrammarCodes">
			<value>-22,-28</value>
		</property>
		<property name="duplicateKeyCodes">
			<value>-104</value>
		</property>
		<property name="dataIntegrityViolationCodes">
			<value>-9</value>
		</property>
		<property name="dataAccessResourceFailureCodes">
			<value>-80</value>
		</property>
	</bean>

    其余数据库的错误码内容也可以从这个文件之中获得。下面我们来看看如何自定义异常处理。上面我们已经知道在org.springframework.jdbc.support包下有sql-error-codes.xml文件,在Spring启动时会自动读取这个文件中的错误码,它为我们预分类了一些错误码,而我们可以加强它,来使用我们自定义的异常。首先,定义一个异常类,我们就来自定义一下前面的-104错误,就是HSQL的重复键的问题:
package org.ourpioneer.vehicle.exception;
import org.springframework.dao.DataIntegrityViolationException;
public class VehicleDuplicateKeyException extends
		DataIntegrityViolationException {
	public VehicleDuplicateKeyException(String msg) {
		super(msg);
	}
	public VehicleDuplicateKeyException(String msg, Throwable cause) {
		super(msg, cause);
	}
}

    之后我们重新新建一个sql-error-codes.xml代码,并将它放到类路径的根目录下,这样Spring会发现它并使用我们自定义的文件,在配置中定义如下:
<bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes">
		<property name="databaseProductName" value="HSQL Database Engine" />
		<property name="useSqlStateForTranslation" value="false" />
		<property name="customTranslations">
			<list>
				<ref local="vehicleDuplicateKeyTranslation" />
			</list>
		</property>
	</bean>
	<bean id="vehicleDuplicateKeyTranslation"
	class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation">
		<property name="errorCodes" value="-104" />
		<property name="exceptionClass"
	value="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyException" />
	</bean>

    HSQL的bean的名称不要改,并将useSqlStateForTranslation置为false,就可以使用我们自己定义的异常类了。在主函数中移除try/catch块,启动程序,我们就可以看到如下内容:

    从启动信息中可以发现Spring发现了我们自定义的sql-error-codes.xml,并替换其中的HSQL数据库处理部分,使用了我们定义的异常,模拟出主键重复的异常后,VehicleDuplicateKeyException就抛出了。除此之外,还可以实现SQLExceptionTranslator接口,并在JDBC模板中注入其实例来实现异常控制,我们来看一下,首先创建一个Translator类:
package org.ourpioneer.vehicle.exception;
import java.sql.SQLException;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.jdbc.support.SQLExceptionTranslator;
public class VehicleDuplicateKeyTranslator implements SQLExceptionTranslator {
	public DataAccessException translate(String task, String sql,
			SQLException ex) {
		if (task == null) {
			task = "";
		}
		if (sql == null) {
		}
		if (ex.getErrorCode() == -104) {
			return new VehicleDuplicateKeyException(buildMessage(task, sql, ex));
		} else {
			return new UncategorizedSQLException(task, sql, ex);
		}
	}
	private String buildMessage(String task, String sql, SQLException ex) {
		return "数据库操作异常:" + task + "; SQL [" + sql + "]; " + ex.getMessage();
	}
}

    其中,要覆盖translate方法,方法有三个参数,task表示当前操作要进行的任务是什么,sql就是执行的sql语句,ex表示SQLException,我们可以从中获取异常信息,其处理代码仅仅捕捉了错误码为-104(HSQL数据库)的错误,其余的配置信息可以根据需要来自行添加。之后要在Spring中重新配置它们:
	<bean id="vehicleDuplicateKeyTranslator"
	class="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyTranslator"></bean>
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="exceptionTranslator" ref="vehicleDuplicateKeyTranslator" />
		<property name="dataSource" ref="dataSource" />
	</bean>
	<bean id="vehicleDAO" class="org.ourpioneer.vehicle.dao.VehicleDAOImpl">
		<property name="jdbcTemplate" ref="jdbcTemplate" />
	</bean>

    调整DAO实现类的代码:
public class VehicleDAOImpl extends SimpleJdbcDaoSupport implements VehicleDAO {
	…	…
	public void insert(final Vehicle vehicle) {
		String sql = "insert into vehicle(ID,PLATE,CHASSIS,COLOR,WHEEL,SEAT) values(?,?,?,?,?,?)";
		getJdbcTemplate().update(sql, vehicle.getId(),vehicle.getPlate(),vehicle.getChassis(),vehicle.getColor(),vehicle.getWheel(),vehicle.getSeat());
	}
…	…
}

    为了进行测试,其它代码可不用修改,这样继续运行测试程序,同时将sql-error-codes.xml文件从类路径的根路径下去除,就可以得到如下结果:

    Spring的JDBC模块在自定义异常处理上也非常灵活,可以选择自己喜欢的方式来实现。希望对使用者有用,欢迎交流,下一部分开始介绍Spring的ORM。
  • 大小: 49 KB
  • 大小: 69.1 KB
  • 大小: 75 KB
  • 大小: 68.6 KB
23
7
分享到:
评论
4 楼 去香山看枫叶 2015-06-01  
不错,不错
3 楼 tan135830778 2014-07-09  
请问报错了我只想捕获异常,代码继续运行,该如何修改?
2 楼 抢街饭 2011-02-11  
   
1 楼 pk3589 2011-01-24  
8错8错8错8错8错

相关推荐

    Spring 数据库动态切换

    数据库的动态切换在很多项目当中都有应用,经我查阅了多篇文档,整合思路最终成功实现数据源的动态切换功能,并稳定运行了一段时间未发现异常。 我的数据源切换时根据域名并配合spring来切换的,不同的域名访问...

    Spring Dao层设计

    Spring 数据库访问的支持。包括统一异常体系和Spring的Template+CallBack的解读

    基于SpringBoot2+Jpa+SpringSecurity+redis+Vue的前后端分离系统

    Sql监控 采用 druid 监控数据库访问性能 技术栈 基础框架:Spring Boot 2.1.0.RELEASE 持久层框架:Spring boot Jpa 安全框架:Spring Security 缓存框架:Redis 日志打印:logback+log4jdbc 接口文档 swagger2 ...

    基于SpringBoot+SpringSecurity的RBAC管理系统源码+数据库+项目说明.zip

    SQL监控:采用druid 监控数据库访问性能 接口管理:方便统一查看管理接口 部门管理:配置系统用户所属部门组织 岗位管理:配置系统用户所属担任职务 字典管理:配置维护系统中较为固定的数据 【技术栈】 1、...

    Spring.3.x企业应用开发实战(完整版).part2

    第11章 使用Spring JDBC访问数据库 11.1 使用Spring JDBC 11.1.1 JDBCTemplate小试牛刀 11.1.2 在DAO中使用JDBCTemplate 11.2 基本的数据操作 11.2.1 更改数据 11.2.2 返回数据库的表自增主键值 11.2.3 批量更改数据...

    使用Java基于MongoDB和SpringData应用.docx

    MongoDB 是一个可扩展的、高性能的、开源的NoSQL数据库,跟传统的数据库不一样,MongoDB并不是将数据存储在表中,他将数据结构化为一个类似于JSON的文档中。...通常,他会转换数据库访问异常到Spring中的异常结构。

    Spring+3.x企业应用开发实战光盘源码(全)

     第8章:介绍了Spring所提供的DAO封装层,这包括Spring DAO的异常体系、数据访问模板等内容。  第9章:介绍了Spring事务管理的工作机制,通过XML、注解等方式进行事务管理配置,同时还讲解了JTA事务配置知识。  ...

    SpringBoot 服务调用异常重试补偿处理

    1. 启动Demo01和Demo02项目 2. 请求 地址:127.0.0.1:8080/demo01/send/post 报文:{"sleepNum":5} 3. 测试目的 ... 停止demo02, 请求demo01,出现网络异常, demo01会执行三次重试后在进行补偿处理

    spring in action英文版

     第1章 开始Spring之旅  1.1 为什么使用Spring  1.1.1 J2EE开发者的一天  1.1.2 Spring的承诺  1.2 Spring是什么  1.3 开始Spring之旅  1.4 理解反向控制  1.4.1 依赖注入  1.4.2 IoC应用...

    spring 帮助文档(chm格式)

    Spring还提供了一个MVC应用框架,可以透明的把AOP集成到你的软件中的途径和一个优秀的异常处理体系, 包括自动从Spring特有的异常体系中映射。 Spring有潜力成为所有企业应用的一站式(即在一个服务点可以完成所有...

    spring+springmvc+mybatis项目案例实现用户角色权限管理

    使用了springmvc统一异常处理 使用了FormattingConversionServiceFactoryBean对于传入参数中日期或数字字符串进行数据转换和数据格式化 使用了SpringContextHolder方便在自定义线程中调用spring已经实例的bean,如...

    Spring 2.0 开发参考手册

    17. 使用Spring进行远程访问与Web服务 17.1. 简介 17.2. 使用RMI暴露服务 17.2.1. 使用 RmiServiceExporter 暴露服务 17.2.2. 在客户端链接服务 17.3. 使用Hessian或者Burlap通过HTTP远程调用服务 17.3.1. 为...

    Spring-Reference_zh_CN(Spring中文参考手册)

    13.10. 处理异常 13.11. 惯例优先原则(convention over configuration) 13.11.1. 对控制器的支持: ControllerClassNameHandlerMapping 13.11.2. 对模型的支持:ModelMap (ModelAndView) 13.11.3. 对视图的支持: ...

    第24次课-1 Spring与Hibernate的整合

    异常包装:Spring能够包装Hibernate的异常,使开发者可以选择恰当的层来处理异常。 24.2 管理SessionFactory Hibernate的SessionFactory,是单个数据库映射关系编译后的内存镜像,是Hibernate执行持久化访问的基础。...

    spring五种事务配置demo

    DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。...

    Spring in Action(第2版)中文版

    5.1.1了解spring数据访问的异常体系 5.1.2数据访问的模板化 5.1.3使用dao支持类 5.2配置数据源 5.2.1使用jndi数据源 5.2.2使用数据源连接池 5.2.3基于jdbc驱动的数据源 5.3在spring里使用jdbc 5.3.1处理失控...

    Spring攻略(第二版 中文高清版).part1

    13.7 在集成测试中访问数据库 536 13.7.1 问题 536 13.7.2 解决方案 536 13.7.3 工作原理 537 13.8 使用Spring的常用测试注解 540 13.8.1 问题 540 13.8.2 解决方案 540 13.8.3 工作原理 541 13.9 ...

    Spring in Action(第二版 中文高清版).part2

    5.1.1 了解Spring数据访问的异常体系 5.1.2 数据访问的模板化 5.1.3 使用DAO支持类 5.2 配置数据源 5.2.1 使用JNDI数据源 5.2.2 使用数据源连接池 5.2.3 基于JDBC驱动的数据源 5.3 在Spring里使用JDBC ...

    Spring in Action(第二版 中文高清版).part1

    5.1.1 了解Spring数据访问的异常体系 5.1.2 数据访问的模板化 5.1.3 使用DAO支持类 5.2 配置数据源 5.2.1 使用JNDI数据源 5.2.2 使用数据源连接池 5.2.3 基于JDBC驱动的数据源 5.3 在Spring里使用JDBC ...

Global site tag (gtag.js) - Google Analytics