Spring JDBC抽象框架所带来的价值将在以下几个方面得以体现:(注:使用了Spring JDBC抽象框架之后,应用开发人员只需要完成斜体字部分的编码工作。)
指定数据库连接参数
打开数据库连接
声明SQL语句
预编译并执行SQL语句
遍历查询结果(如果需要的话)
处理每一次遍历操作
处理抛出的任何异常
处理事务
关闭数据库连接
Spring将替我们完成所有单调乏味的JDBC底层细节处理工作。
Spring JDBC抽象框架由四个包构成:core
、 dataSource
、object
以及support
。
org.springframework.jdbc.core
包由JdbcTemplate
类以及相关的回调接口(callback interface)和类组成。
org.springframework.jdbc.datasource
包由一些用来简化DataSource
访问的工具类,以及各种DataSource
接口的简单实现(主要用于单元测试以及在J2EE容器之外使用JDBC)组成。工具类提供了一些静态方法,诸如通过JNDI获取数据连接以及在必要的情况下关闭这些连接。它支持绑定线程的连接,比如被用于DataSourceTransactionMan
的连接。
接下来,org.springframework.jdbc.object
包由封装了查询、更新以及存储过程的类组成,这些类的对象都是线程安并且可重复使用的。它们类似于JDO,与JDO的不同之处在于查询结果与数据库是“断开连接”的。它们是在org.springframework.jdbc.core
包的基础上对JDBC更高层次的抽象。
后,org.springframework.jdbc.support
包提供了一些SQLException
的转换类以及相关的工具类。
在JDBC处理过程中抛出的异常将被转换成org.springframework.dao
包中定义的异常。因此使用Spring JDBC进行开发将不需要处理JDBC或者特定的RDBMS才会抛出的异常。所有的异常都是unchecked exception,这样我们就可以对传递到调用者的异常进行有选择的捕获。
这是在JDBC核心包中重要的类。它简化了JDBC的使用,因为它处理了资源的建立和释放。它帮助你避免一些常见的错误,比如忘了总要关闭连接。它运行核心的JDBC工作流,如Statement的建立和执行,而只需要应用程序代码提供SQL和提取结果。这个类执行SQL查询,更新或者调用存储过程,模拟结果集的迭代以及提取返回参数值。它还捕捉JDBC的异常并将它们转换成 org.springframework.dao包中定义的通用的,能够提供更多信息的异常体系。
使用这个类的代码只需要根据明确定义的一组契约来实现回调接口。 PreparedStatementCreator
这个类可以直接通过数据源的引用实例化,然后在服务中使用,也可以在ApplicationContext中产生并作为bean的引用给服务使用。注意:数据源应当总是作为一个bean在ApplicationContext中配置,种情况它被直接传递给服务,第二种情况给JdbcTemplate。因为这个类把回调接口和SQLExceptionTranslator接口作为参数表示,所以没有必要为它定义子类。这个类执行的所有SQL都会被记入日志。
为了从数据库获得数据,我们需要得到数据库的连接。 Spring采用的方法是通过一个数据源。 数据源是JDBC规范的一部分,它可以被认为是一个通用的连接工厂。它允许容器或者框架将在应用程序代码中隐藏连接池和事务的管理操作。开发者将不需要知道连接数据库的任何细节,那是设置数据源的管理员的责任。虽然你很可能在开发或者测试的时候需要兼任两种角色,但是你并不需要知道实际产品中的数据源是如何配置的。
使用Spring的JDBC层,你可以从JNDI得到一个数据源,也可以通过使用Spring发行版提供的实现自己配置它。后者对于脱离Web容器的单元测试是十分便利的。我们将在本节中使用DriverManagerDataSource实现,当然以后还会提到其他的一些的实现。 DriverManagerDataSource和传统的方式一样获取JDBC连接。为了让DriverManager可以装载驱动类,你必须指定JDBC驱动完整的类名。然后你必须提供相对于各种JDBC驱动的不同的URL。你必须参考你所用的驱动的文档,以获得需要使用的正确参数。后,你还必须提供用来连接数据库的用户名和密码下面这个例子说明如何配置DriverManagerDataSource:
DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName( "org.hsqldb.jdbcDriver"); dataSource.setUrl( "jdbc:hsqldb:hsql://localhost:"); dataSource.setUsername( "sa"); dataSource.setPassword( "");
SQLExceptionTranslator是一个需要实现的接口,它被用来处理SQLException和我们的数据访问异常org.springframework.dao.DataAccessException之间的转换。
实现可以是通用的(比如使用JDBC的SQLState值),也可以为了更高的度特殊化 (比如使用Oracle的ErrorCode)。
SQLErrorCodeSQLException
SQLErrorCodeSQLException
使用子类实现的自定义转换。要注意的是这个类本身就是一个具体类,并可以直接使用, 在这种情况下,将不使用这条规则。
使用ErrorCode的匹配。在默认情况下,ErrorCode是从SQLErrorCodesFactory得到的。它从classpath中寻找ErrorCode,并把从数据库metadata中得到的数据库名字嵌入它们。
如果以上规则都无法匹配,那么是用SQLStateSQLExceptionTran
SQLErrorCodeSQLException
public class MySQLErrorCodesTransalat
在这个例子中,只有特定的ErrorCode'-12345'被转换了,其他的错误被简单的返回,由默认的转换实现来处理。要使用自定义转换器时,需要通过setExceptionTranslator 方法将它传递给JdbcTemplate,并且在所有需要使用自定义转换器的数据访问处理中使用这个JdbcTemplate 下面是一个如何使用自定义转换器的例子:
// create a JdbcTemplate and set data source JdbcTemplate jt = new JdbcTemplate(); jt.setDataSource(dataSource); // create a custom translator and set the datasource for the default translation lookup MySQLErrorCodesTransalat
这个自定义的转换器得到了一个数据源,因为我们仍然需要默认的转换器在sql-error-codes.xml中查找ErrorCode。
要执行一个SQL,几乎不需要代码。你所需要的部是一个数据源和一个JdbcTemplate。一旦你得到了它们,你将可以使用JdbcTemplate提供的大量方便的方法。下面是一个例子,它显示了建立一张表的小的但有完整功能的类。
import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; public class ExecuteAStatement { private JdbcTemplate jt; private DataSource dataSource; public void doExecute() { jt = new JdbcTemplate(dataSource); jt.execute("create table mytable (id integer, name varchar(100))"); } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } }
除了execute方法,还有大量的查询方法。其中的一些被用来执行那些只返回单个值的查询。也许你需要得到合计或者某一行中的一个特定的值。如果是这种情况,你可以使用queryForInt, queryForLong或者queryForObject。后者将会把返回的JDBC类型转换成参数中指定的Java类。如果类型转换无效,那么将会抛出一个InvalidDataAccessApiUsag
import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; public class RunAQuery { private JdbcTemplate jt; private DataSource dataSource; public int getCount() { jt = new JdbcTemplate(dataSource); int count = jt.queryForInt("select count(*) from mytable"); return count; } public String getName() { jt = new JdbcTemplate(dataSource); String name = (String) jt.queryForObject("select name from mytable", java.lang.String.class); return name; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } }
除了得到单一结果的查询方法之外,还有一些方法,可以得到一个包含查询返回的数据的List。其中通用的一个方法是queryForList,它返回一个List,其中每一项都是一个表示字段值的Map。你用下面的代码在上面的例子中增加一个方法来得到一个所有记录行的List:
public List getList() { jt = new JdbcTemplate(dataSource); List rows = jt.queryForList("select * from mytable"); return rows; }
返回的List会以下面的形式: [{name=Bob, id=1}, {name=Mary, id=2}].
(6)更新数据库:
还有很多更新的方法可以供你使用。我将展示一个例子,说明通过某一个主键更新一个字段。 在这个例子里,我用了一个使用榜定参数的SQL Statement。大多数查询和更新的方法都有这个功能。 参数值通过对象数组传递。
import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; public class ExecuteAnUpdate { private JdbcTemplate jt; private DataSource dataSource; public void setName(int id, String name) { jt = new JdbcTemplate(dataSource); jt.update("update mytable set name = ? where id = ?", new Object[] {name, new Integer(id)}); } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } }
本文标题:JDBC进行数据访问的初步学习,责任编辑:宏鹏,来源:武汉北大青鸟鲁广校区栏目,于2012-12-09 09:27:51发布于北大青鸟鲁广校区。JDBC进行数据访问的初步学习。
预约将免费领取7天课程体验卡
只为您方便就学
专业老师24小时1对1学习指导
定制专属于你的专属学习方案
微信号:17740513250
微信号:17740513250