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进行定制的话,可能是它的子类名)。
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中共享该实例。
SimpleJdbcTemplate类
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);
}
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("");
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中获取错误代码集。
分享到:
相关推荐
它提供了在JBoss AS环境下运行Spring应用所需的类和接口,确保Spring的配置和组件能够在JBoss服务器上正常启动和运行。这个版本可能包含对JBoss AS特定版本的适配和优化,以便更好地与Spring框架协作。 4. **`jboss...
VFS(Virtual File System,虚拟文件系统)是JBoss AS中的一个核心组件,它为处理不同类型的文件系统提供了统一的抽象层。在Tomcat等其他服务器中,Spring可能直接操作文件系统,但在JBoss中,由于VFS的存在,文件...
在Java开发领域,Spring Web MVC框架和JBoss日志库是两个非常重要的组件。Spring Web MVC是Spring框架的一部分,主要用于构建Web应用程序,而JBoss的日志库则为开发者提供了强大的日志处理能力。这里我们主要探讨...
EJB(Enterprise JavaBeans)是Java平台上的核心组件,它提供了一种标准的方式来构建分布式、事务处理和安全的业务逻辑。 首先,让我们了解EJB 3.x的关键特性。EJB 3.x引入了更加简洁和面向对象的API,简化了开发...
9. **服务发现和依赖注入**:JBoss 5采用了Spring框架的依赖注入(DI)理念,允许组件之间松耦合。`jboss.spring`包中包含Spring的集成代码,帮助理解如何在JBoss中使用DI。 10. **国际化与本地化**:JBoss支持多...
JNDI 架构包括了核心组件,如端口(Port)、RMI 端口(RmiPort)、绑定地址(BindAddress)等,这些组件共同确保了服务的正常运行。 **JNDI 在 JBoss 中的配置** 在 JBoss 中使用 JNDI 需要配置一系列的属性,例如...
- **本教程**:主要介绍了JBoss Seam的基本概念、核心组件以及通过一系列示例项目来学习Seam的实际应用。 #### 二、Seam基础知识与实例分析 ##### 2.1 第一个Seam应用:注册示例 - **实体类**:`User.java`定义了...
通过阅读《JBoss开发者手册》,开发者可以深入了解如何高效地利用JBoss开发和部署企业级应用,解决实际遇到的问题,并充分利用其提供的各种服务和特性。同时,这份手册也会介绍一些最佳实践,帮助开发者遵循行业标准...
本文将深入探讨如何将IBM WebSphere MQ(简称IBM MQ)与JBoss应用程序服务器整合,并利用Spring框架来实现消息的读写。这一整合有助于提升系统的可扩展性和解耦性,使应用程序能够通过消息传递进行异步通信。 首先...
本项目“HornetQ-JBoss-TS-MySQL-Tomcat-Spring-master”就是一个关于Jboss事物处理的实践案例,涵盖了多个关键组件。 首先,**HornetQ**是JBoss的一个开源消息传递系统,它提供了高性能、高可用性和可扩展性的消息...
需要注意的是,在实现过程中要充分利用JBoss提供的各种框架和工具,比如Spring、Hibernate等。 4. **部署服务**:将开发完成的服务部署到JBoss服务器上,并确保所有服务都能正常工作。 5. **测试与优化**:最后一步...
1. **Spring框架集成**:JBoss 可以无缝集成Spring框架,允许开发者利用Spring的强大功能,如依赖注入、AOP(面向切面编程)等。 2. **数据库连接**:JBoss 支持多种数据库,如MySQL、Oracle、PostgreSQL等,通过...
此外,理解JBoss的类加载机制有助于解决类冲突问题。 对于JBoss中的EJB,你需要理解实体Bean、会话Bean和消息驱动Bean的不同角色及其用法。实体Bean通常用于持久化数据,会话Bean处理业务逻辑,而消息驱动Bean则...
接着,深入到Java EE的核心组件,如Servlet、JSP、EJB等,讲解如何在JBoss上部署和运行这些组件。对于EJB,会详细讨论实体Bean、会话Bean和消息驱动Bean的开发与管理,包括生命周期管理、事务处理、安全性设置等内容...
JSF是Java EE的一部分,它的核心是组件模型和事件驱动机制。JSF组件库包括一系列可重用的UI组件,如按钮、文本框、表格等,开发者可以通过XML配置或Java代码来创建和布局页面。JSF通过EL(Expression Language)进行...
【JBoss + EJB】是Java企业版(Java EE)中的关键组成部分,JBoss是一个开源的应用服务器,而EJB(Enterprise JavaBeans)是Java EE中用于构建可复用的、安全的、分布式的企业级应用程序的核心组件。这篇博客文章将...
2. **模块化架构**:JBoss采用模块化设计,将各种服务和组件打包在独立的JAR或WAR文件中,使得配置和管理更为灵活。 3. **热部署**:允许开发者在运行时更新应用程序,无需重启服务器,提高了开发效率。 4. **EJB ...
1. **Spring 框架核心组件** - `org.springframework`:这是Spring框架的核心模块,包含了IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)等核心功能。如`spring-beans`...
以下是对JBoss EAP 7.0的一些核心知识点的详细说明: 1. **Java EE 7支持**:JBoss EAP 7.0遵循Java Enterprise Edition 7标准,包括Web Profile和Full Profile。这涵盖了诸如Servlet 3.1、JPA 2.1、JSF 2.2、CDI ...
在JBoss之前,其基于模块化的JMX内核已经相当成熟,但为了保持领先,他们希望能够集成如EJB3、JPA、Spring、Guice等不同POJO组件模型,消除它们之间的差异。 JBoss Microcontainer项目的核心目标是提供一系列特性,...