- 浏览: 145494 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (137)
- 服务器配置 (6)
- 密码忘记怎么办? (1)
- mysql的一些小技巧 (3)
- 查看apache2日志 (1)
- 图片切图 (1)
- apache (1)
- 谷歌地图 (1)
- 缓存 (2)
- hibernate (1)
- yum的安装!!! (1)
- 插件管理 (1)
- linux (1)
- jdk安装 (1)
- 获取流 (1)
- mongodb (0)
- mysql更改数据库 (0)
- 邮箱验证 (0)
- 邮箱验证新规则 (1)
- 数据库 (1)
- 网站开发 (1)
- redis (1)
- Node.js安装 (1)
- morphia (1)
- mongodb启动 (1)
- amoeba (1)
- mysql数据库优化 (1)
- 解析数据 (1)
- 文件授权 (1)
- 短链接 (1)
- 安装 (1)
- svn (1)
- thrift启动问题 (1)
最新评论
-
hzxlb910:
代码重新整理一下就好了
JdbcTemplate类 -
曾老师:
给你自个看去吧
jquery.form.js的使用 -
至尊宝_唯一:
写的似乎有点简单了,能谈谈各种datasource的优缺点吗或 ...
使用dataSource小结
11.2. 利用JDBC核心类实现JDBC的基本操作和错误处理
11.2.1. JdbcTemplate类
JdbcTemplate是core包的核心类。它替我们完成了资源的创建以及释放工作,从而简化了我们对JDBC的使用。它还可以帮助我们避免一些常见的错误,比如忘记关闭数据库连接。JdbcTemplate将完成JDBC核心处理流程,比如SQL语句的创建、执行,而把SQL语句的生成以及查询结果的提取工作留给我们的应用代码。它可以完成SQL查询、更新以及调用存储过程,可以对ResultSet进行遍历并加以提取。它还可以捕获JDBC异常并将其转换成org.springframework.dao包中定义的,通用的,信息更丰富的异常。
使用JdbcTemplate进行编码只需要根据明确定义的一组契约来实现回调接口。PreparedStatementCreator回调接口通过给定的Connection创建一个PreparedStatement,包含SQL和任何相关的参数。CallableStatementCreateor实现同样的处理,只不过它创建的是CallableStatement。RowCallbackHandler接口则从数据集的每一行中提取值。
我们可以在一个service实现类中通过传递一个DataSource引用来完成JdbcTemplate的实例化,也可以在application context中配置一个JdbcTemplate bean,来供service使用。需要注意的是DataSource在application context总是配制成一个bean,第一种情况下,DataSource bean将传递给service,第二种情况下DataSource bean传递给JdbcTemplate bean。因为JdbcTemplate使用回调接口和SQLExceptionTranslator接口作为参数,所以一般情况下没有必要通过继承JdbcTemplate来定义其子类。
JdbcTemplate中使用的所有SQL将会以“DEBUG”级别记入日志(一般情况下日志的category是JdbcTemplate相应的全限定类名,不过如果需要对JdbcTemplate进行定制的话,可能是它的子类名)。
11.2.2. NamedParameterJdbcTemplate类
NamedParameterJdbcTemplate类增加了在SQL语句中使用命名参数的支持。在此之前,在传统的SQL语句中,参数都是用'?'占位符来表示的。 NamedParameterJdbcTemplate类内部封装了一个普通的JdbcTemplate,并作为其代理来完成大部分工作。下面的内容主要针对NamedParameterJdbcTemplate与JdbcTemplate的不同之处来加以说明,即如何在SQL语句中使用命名参数。
通过下面的例子我们可以更好地了解NamedParameterJdbcTemplate的使用模式(在后面我们还有更好的使用方式)。
// some JDBC-backed DAO class...
public int countOfActorsByFirstName(String firstName) {
String sql = "select count(0) from T_ACTOR where first_name = :first_name";
NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(this.getDataSource());
SqlParameterSource namedParameters = new MapSqlParameterSource("first_name", firstName);
return template.queryForInt(sql, namedParameters);
}
在上面例子中,sql变量使用了命名参数占位符“first_name”,与其对应的值存在namedParameters变量中(类型为MapSqlParameterSource)。
如果你喜欢的话,也可以使用基于Map风格的名值对将命名参数传递给NamedParameterJdbcTemplate(NamedParameterJdbcTemplate实现了NamedParameterJdbcOperations接口,剩下的工作将由调用该接口的相应方法来完成,这里我们就不再赘述):
// some JDBC-backed DAO class...
public int countOfActorsByFirstName(String firstName) {
String sql = "select count(0) from T_ACTOR where first_name = :first_name";
NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(this.getDataSource());
Map namedParameters = new HashMap();
namedParameters.put("first_name", firstName);
return template.queryForInt(sql, namedParameters);
}
另外一个值得一提的特性是与NamedParameterJdbcTemplate位于同一个包中的SqlParameterSource接口。在前面的代码片断中我们已经看到了该接口的实现(即MapSqlParameterSource类),SqlParameterSource可以用来作为NamedParameterJdbcTemplate命名参数的来源。MapSqlParameterSource类是一个非常简单的实现,它仅仅是一个java.util.Map适配器,当然其用法也就不言自明了(如果还有不明了的,可以在Spring的JIRA系统中要求提供更多的相关资料)。
SqlParameterSource接口的另一个实现--BeanPropertySqlParameterSource为我们提供了更有趣的功能。该类包装一个类似JavaBean的对象,所需要的命名参数值将由包装对象提供,下面我们使用一个例子来更清楚地说明它的用法。
// some JavaBean-like class...
public class Actor {
private Long id;
private String firstName;
private String lastName;
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
public Long getId() {
return this.id;
}
// setters omitted...
}
// some JDBC-backed DAO class...
public int countOfActors(Actor exampleActor) {
// notice how the named parameters match the properties of the above 'Actor' class
String sql = "select count(0) from T_ACTOR where first_name = :firstName and last_name = :lastName";
NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(this.getDataSource());
SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(exampleActor);
return template.queryForInt(sql, namedParameters);
}
大家必须牢记一点:NamedParameterJdbcTemplate类内部包装了一个标准的JdbcTemplate类。如果你需要访问其内部的JdbcTemplate实例(比如访问JdbcTemplate的一些方法)那么你需要使用getJdbcOperations()方法返回的JdbcOperations接口。(JdbcTemplate实现了JdbcOperations接口)。
NamedParameterJdbcTemplate类是线程安全的,该类的最佳使用方式不是每次操作的时候实例化一个新的NamedParameterJdbcTemplate,而是针对每个DataSource只配置一个NamedParameterJdbcTemplate实例(比如在Spring IoC容器中使用Spring IoC来进行配置),然后在那些使用该类的DAO中共享该实例。
11.2.3. SimpleJdbcTemplate类
注意
请注意该类所提供的功能仅适用于Java 5 (Tiger)。
SimpleJdbcTemplate类是JdbcTemplate类的一个包装器(wrapper),它利用了Java 5的一些语言特性,比如Varargs和Autoboxing。对那些用惯了Java 5的程序员,这些新的语言特性还是很好用的。
SimpleJdbcTemplate 类利用Java 5的语法特性带来的好处可以通过一个例子来说明。在下面的代码片断中我们首先使用标准的JdbcTemplate进行数据访问,接下来使用SimpleJdbcTemplate做同样的事情。
// classic JdbcTemplate-style...
public Actor findActor(long id) {
String sql = "select id, first_name, last_name from T_ACTOR where id = ?";
RowMapper mapper = new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Actor actor = new Actor();
actor.setId(rs.getLong(Long.valueOf(rs.getLong("id"))));
actor.setFirstName(rs.getString("first_name"));
actor.setLastName(rs.getString("last_name"));
return actor;
}
};
// normally this would be dependency injected of course...
JdbcTemplate jdbcTemplate = new JdbcTemplate(this.getDataSource());
// notice the cast, and the wrapping up of the 'id' argument
// in an array, and the boxing of the 'id' argument as a reference type
return (Actor) jdbcTemplate.queryForObject(sql, mapper, new Object[] {Long.valueOf(id)});
}
下面是同一方法的另一种实现,惟一不同之处是我们使用了SimpleJdbcTemplate,这样代码显得更加清晰。
// SimpleJdbcTemplate-style...
public Actor findActor(long id) {
String sql = "select id, first_name, last_name from T_ACTOR where id = ?";
ParameterizedRowMapper<Actor> mapper = new ParameterizedRowMapper<Actor>() {
// notice the return type with respect to Java 5 covariant return types
public Actor mapRow(ResultSet rs, int rowNum) throws SQLException {
Actor actor = new Actor();
actor.setId(rs.getLong("id"));
actor.setFirstName(rs.getString("first_name"));
actor.setLastName(rs.getString("last_name"));
return actor;
}
};
// again, normally this would be dependency injected of course...
SimpleJdbcTemplate simpleJdbcTemplate = new SimpleJdbcTemplate(this.getDataSource());
return simpleJdbcTemplate.queryForObject(sql, mapper, id);
}
11.2.4. DataSource接口
为了从数据库中取得数据,我们首先需要获取一个数据库连接。 Spring通过DataSource对象来完成这个工作。 DataSource是JDBC规范的一部分, 它被视为一个通用的数据库连接工厂。通过使用DataSource, Container或Framework可以将连接池以及事务管理的细节从应用代码中分离出来。 作为一个开发人员,在开发和测试产品的过程中,你可能需要知道连接数据库的细节。 但在产品实施时,你不需要知道这些细节。通常数据库管理员会帮你设置好数据源。
在使用Spring JDBC时,你既可以通过JNDI获得数据源,也可以自行配置数据源( 使用Spring提供的DataSource实现类)。使用后者可以更方便的脱离Web容器来进行单元测试。 这里我们将使用DriverManagerDataSource,不过DataSource有多种实现, 后面我们会讲到。使用DriverManagerDataSource和你以前获取一个JDBC连接 的做法没什么两样。你首先必须指定JDBC驱动程序的全限定名,这样DriverManager 才能加载JDBC驱动类,接着你必须提供一个url(因JDBC驱动而异,为了保证设置正确请参考相关JDBC驱动的文档), 最后你必须提供一个用户连接数据库的用户名和密码。下面我们将通过一个例子来说明如何配置一个 DriverManagerDataSource:
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
dataSource.setUsername("sa");
dataSource.setPassword("");
11.2.5. SQLExceptionTranslator接口
SQLExceptionTranslator是一个接口,如果你需要在 SQLException和org.springframework.dao.DataAccessException之间作转换,那么必须实现该接口。
转换器类的实现可以采用一般通用的做法(比如使用JDBC的SQLState code),如果为了使转换更准确,也可以进行定制(比如使用Oracle的error code)。
SQLErrorCodeSQLExceptionTranslator是SQLExceptionTranslator的默认实现。 该实现使用指定数据库厂商的error code,比采用SQLState更精确。 转换过程基于一个JavaBean(类型为SQLErrorCodes)中的error code。 这个JavaBean由SQLErrorCodesFactory工厂类创建,其中的内容来自于 "sql-error-codes.xml"配置文件。该文件中的数据库厂商代码基于Database MetaData信息中的 DatabaseProductName,从而配合当前数据库的使用。
SQLErrorCodeSQLExceptionTranslator使用以下的匹配规则:
首先检查是否存在完成定制转换的子类实现。通常SQLErrorCodeSQLExceptionTranslator 这个类可以作为一个具体类使用,不需要进行定制,那么这个规则将不适用。
接着将SQLException的error code与错误代码集中的error code进行匹配。 默认情况下错误代码集将从SQLErrorCodesFactory取得。 错误代码集来自classpath下的sql-error-codes.xml文件, 它们将与数据库metadata信息中的database name进行映射。
如果仍然无法匹配,最后将调用fallbackTranslator属性的translate方法,SQLStateSQLExceptionTranslator类实例是默认的fallbackTranslator。
SQLErrorCodeSQLExceptionTranslator可以采用下面的方式进行扩展:
public class MySQLErrorCodesTranslator extends SQLErrorCodeSQLExceptionTranslator {
protected DataAccessException customTranslate(String task, String sql, SQLException sqlex) {
if (sqlex.getErrorCode() == -12345) {
return new DeadlockLoserDataAccessException(task, sqlex);
}
return null;
}
}
在上面的这个例子中,error code为'-12345'的SQLException 将采用该转换器进行转换,而其他的error code将由默认的转换器进行转换。 为了使用该转换器,必须将其作为参数传递给JdbcTemplate类 的setExceptionTranslator方法,并在需要使用这个转换器器的数据 存取操作中使用该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
MySQLErrorCodesTransalator tr = new MySQLErrorCodesTransalator();
tr.setDataSource(dataSource);
jt.setExceptionTranslator(tr);
// use the JdbcTemplate for this SqlUpdate
SqlUpdate su = new SqlUpdate();
su.setJdbcTemplate(jt);
su.setSql("update orders set shipping_charge = shipping_charge * 1.05");
su.compile();
su.update();
在上面的定制转换器中,我们给它注入了一个数据源,因为我们仍然需要 使用默认的转换器从sql-error-codes.xml中获取错误代码集。
11.2.6. 执行SQL语句
我们仅需要非常少的代码就可以达到执行SQL语句的目的,一旦获得一个 DataSource和一个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;
}
}
11.2.7. 执行查询
除了execute方法之外,JdbcTemplate还提供了大量的查询方法。 在这些查询方法中,有很大一部分是用来查询单值的。比如返回一个汇总(count)结果 或者从返回行结果中取得指定列的值。这时我们可以使用queryForInt(..)、 queryForLong(..)或者queryForObject(..)方法。 queryForObject方法用来将返回的JDBC类型对象转换成指定的Java对象,如果类型转换失败将抛出 InvalidDataAccessApiUsageException异常。 下面的例子演示了两个查询的用法,一个返回int值,另一个返回 String。
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", String.class);
return name;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}
除了返回单值的查询方法,JdbcTemplate还提供了一组返回List结果 的方法。List中的每一项对应查询返回结果中的一行。其中最简单的是queryForList方法, 该方法将返回一个List,该List中的每一条 记录是一个Map对象,对应应数据库中某一行;而该Map 中的每一项对应该数据库行中的某一列值。下面的代码片断接着上面的例子演示了如何用该方法返回表中 所有记录:
public List getList() {
jt = new JdbcTemplate(dataSource);
List rows = jt.queryForList("select * from mytable");
return rows;
}
返回的结果集类似下面这种形式:
[{name=Bob, id=1}, {name=Mary, id=2}]
11.2.8. 更新数据库
JdbcTemplate还提供了一些更新数据库的方法。 在下面的例子中,我们根据给定的主键值对指定的列进行更新。 例子中的SQL语句中使用了“?”占位符来接受参数(这种做法在更新和查询SQL语句中很常见)。 传递的参数值位于一个对象数组中(基本类型需要被包装成其对应的对象类型)。
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;
}
}
相关推荐
Spring 框架 JdbcTemplate 类中查询方法介绍 JdbcTemplate 是 Spring 框架中 org.springframework.jdbc.core 包提供的 JDBC 模板类,它是核心类,其他模板类都是基于它封装完成的。JdbcTemplate 类主要提供四类方法...
Spring的JdbcTemplate是Spring框架中用于简化数据库操作的工具类,它是基于JDBC但又抽象出了一层,避免了直接与数据库驱动API交互,从而提高了代码的可读性和可维护性。本文将深入探讨Spring JdbcTemplate的常用方法...
《深入解析Spring JdbcTemplate》 Spring JDBC Template是Spring框架中用于简化JDBC操作的一个核心组件,它是Spring对JDBC API的封装,旨在提供一个更加简洁、健壮且可测试的数据库访问层。在这个实例工程中,我们...
Spring框架为简化这一过程提供了JdbcTemplate类,它基于Java Database Connectivity (JDBC) API,但通过一系列抽象和自动处理,使得数据库操作更加安全、易用且易于测试。JdbcTemplate是Spring JDBC模块的核心组件,...
SpringJdbcTemplate是一个模板类,它提供了大量的方法来执行SQL查询、更新、存储过程等操作。这些方法会自动处理JDBC相关的资源关闭、异常转换等细节,使得代码更加整洁和健壮。 2. **数据库自适应** Spring...
spring-jdbc.jar包含了Spring对JDBC的抽象层,包括JdbcTemplate类和SimpleJdbcInsert、SimpleJdbcCall等工具类。JdbcTemplate提供了一套模板化的API,用于执行SQL查询、更新、存储过程等操作,同时自动处理结果集、...
这个文件提供了JdbcTemplate类和其他相关支持类。 2. **JDBC驱动**:根据你使用的数据库类型,你需要相应的JDBC驱动。例如,如果你使用的是MySQL,你需要`mysql-connector-java.jar`;如果是Oracle,则需要`ojdbc....
commons-logging-1.2.jar spring-jdbc-5.1.10.RELEASE.jar spring-core-5.1.10.RELEASE.jar spring-beans-5.1.10.RELEASE.jar ...
1. `spring-jdbc.jar`:这是Spring JDBC模块的核心库,包含了JdbcTemplate类和其他相关的接口和类。这个jar包提供了对JDBC操作的封装,使得你可以方便地执行SQL语句并处理结果。 2. `spring-tx.jar`:Spring的事务...
JdbcTemplate主要提供以下五类方法;JdbcTemplate类支持的回调类;并附例子
在这个名为“在项目中导入.rar”的压缩包里,包含了几个关键的Java库,它们是JDBC连接池和JDBCTemplate类的jar包。这些组件能够极大地提升数据库操作的性能,减少资源消耗,并优化用户访问体验。 首先,让我们了解...
JdbcTemplate类通过模板设计模式帮助我们消除了冗长的代码,只做需要做的事情(即可变部分),并且帮我们做哪些固定部分,如连接的创建及关闭。JdbcTemplate类对可变部分采用回调接口方式实现,如ConnectionCallback...
`JdbcTemplateExtend.java`可能扩展了`JdbcTemplate`类,添加了对游标分页的支持。它可能包含了一个或多个方法,用于封装上述步骤,使代码更加简洁易用。 在实际应用中,我们可能还需要考虑并发和性能优化,例如,...
4. 在DAO类中注入JdbcTemplate对象,这通常是通过Spring的依赖注入特性完成的。 5. 创建与数据库表对应的实体类,用于在Java代码中表示表中的数据。 6. 编写Service和DAO类中实现具体数据库操作的方法,如添加、删除...
在源码中,可以看到JdbcTemplate类如何组织这些操作,如`execute()`、`queryForList()`、`update()`等方法。 `PropertyPlaceholderConfigurer`是Spring框架中的一个bean,用于处理属性占位符,如`${property}`。它...
使用Spring的声明式事务管理,我们可以在Bean的类或方法上添加`@Transactional`注解,例如: ```java @Service public class UserService { @Autowired private JdbcTemplate jdbcTemplate; @Transactional ...
在`jdbcTemplate`压缩包文件中,可能包含了实现上述功能的类、配置文件以及其他辅助工具类。这些文件可以帮助我们理解项目中如何自定义和使用`JDBCTemplate`。通过查看这些源码,我们可以学习到如何在实际项目中优化...
通过定义一个泛型接口,我们可以创建一个通用的数据访问对象(DAO),这个DAO可以处理任何类型的实体类,只要它们遵循一定的规则,比如拥有ID字段。这样,我们就只需要编写一次DAO的实现,就可以为不同的数据表提供...