JDBC功能组件
DbUtils库是一组类,旨在简化使用JDBC。JDBC资源清理代码是平凡的,容易出错的工作,这些类抽象出所有清理任务的代码,使用JDBC你首先只需要做的是:查询和更新数据。
- 没有资源泄漏的可能性。正确的JDBC代码并不难但耗时且乏味。这常常会导致连接泄漏,可能很难追踪。
- 更清洁、更清晰的持久性代码。代码的数量需要在数据库中保存数据大大减少。剩下的代码清晰地表达你的意图,没有因为资源清理而杂乱无章。
- 从结果集自动填充JavaBean属性。你不需要手动通过调用setter方法将列值复制到bean实例。每一行的结果集可以表示为一个完全填充的bean实例。
包范围
DbUtils被设计为:
- 小。你应该能够在很短的时间理解整个包。
- 透明——DbUtils并不在幕后做任何魔法。你给它一个查询,它执行它,并为您清理。
- 快——你不需要创建许多临时对象与DbUtils工作。
DbUtils不是:
- 一个对象/关系映射——已经有很多好的ORM工具了。DbUtils是让开发人员使用JDBC简洁。
- 一个DAO框架——DbUtils可以用来构建一个DAO框架。
- 通用的面向对象的抽象数据库对象如表、列或只主键
- 任何一个重量级框架——这里的目标是一个简单的和易于使用的JDBC助手库。
使用示例
基本使用
DbUtils是很小的类库,所以你不会花很长时间去了解每个类的javadoc。它的核心类/接口是QueryRunner和 ResultSetHandler。你不需要知道其他类。
// Create a ResultSetHandler implementation to convert the
// first row into an Object[].
ResultSetHandler<Object[]> h = new ResultSetHandler<Object[]>() {
public Object[] handle(ResultSet rs) throws SQLException {
if (!rs.next()) {
return null;
}
ResultSetMetaData meta = rs.getMetaData();
int cols = meta.getColumnCount();
Object[] result = new Object[cols];
for (int i = 0; i < cols; i++) {
result[i] = rs.getObject(i + 1);
}
return result;
}
};
// Create a QueryRunner that will use connections from
// the given DataSource
QueryRunner run = new QueryRunner(dataSource);
// Execute the query and get the results back from the handler
Object[] result = run.query(
"SELECT * FROM Person WHERE name=?", h, "John Doe");
你也可以使用java.sql.Connection代替DataSource执行之前的查询。注意,本例中您需要负责关闭连接。
ResultSetHandler<Object[]> h = ... // Define a handler the same as above example
// No DataSource so we must handle Connections manually
QueryRunner run = new QueryRunner();
Connection conn = ... // open a connection
try{
Object[] result = run.query(
conn, "SELECT * FROM Person WHERE name=?", h, "John Doe");
// do something with the result
} finally {
// Use this helper method so we don't have to check for null
DbUtils.close(conn);
}
你不仅可以从数据库获取数据,还可以插入或更新的数据。下面的例子将首先将一个人插入到数据库,然后改变人的高度。
QueryRunner run = new QueryRunner( dataSource );
try
{
// Execute the SQL update statement and return the number of
// inserts that were made
int inserts = run.update( "INSERT INTO Person (name,height) VALUES (?,?)",
"John Doe", 1.82 );
// The line before uses varargs and autoboxing to simplify the code
// Now it's time to rise to the occation...
int updates = run.update( "UPDATE Person SET height=? WHERE name=?",
2.05, "John Doe" );
// So does the line above
}
catch(SQLException sqle) {
// Handle it
}
对于长时间运行的调用可以使用AsyncQueryRunner执行异步调用。AsyncQueryRunner类有同QueryRunner相同的方法;只是这些方法返回Callable。
ExecutorCompletionService<Integer> executor =
new ExecutorCompletionService<Integer>( Executors.newCachedThreadPool() );
AsyncQueryRunner asyncRun = new AsyncQueryRunner( dataSource );
try
{
// Create a Callable for the update call
Callable<Integer> callable = asyncRun.update( "UPDATE Person SET height=? WHERE name=?",
2.05, "John Doe" );
// Submit the Callable to the executor
executor.submit( callable );
} catch(SQLException sqle) {
// Handle it
}
// Sometime later (or in another thread)
try
{
// Get the result of the update
Integer updates = executor.take().get();
} catch(InterruptedException ie) {
// Handle it
}
ResultSetHandler实现
在上面的示例中我们实现了ResultSetHandler接口,将结果集的第一行转为类一个Object[]。这是一个相当通用的实现,可以跨多个项目重用。在DbUtils 的org.apache.commons.dbutils.handlers包中提供了一组ResultSetHandler实现,执行常见的结果集转换成数组,Map和javabean。每一个实现都有一个版本是转换结果集第一行,另外一个版本是转换结果集所有行。我们将从一个示例开始使用BeanHandler从ResultSet获取第一行,然后把它变成一个JavaBean。
QueryRunner run = new QueryRunner(dataSource);
// Use the BeanHandler implementation to convert the first
// ResultSet row into a Person JavaBean.
ResultSetHandler<Person> h = new BeanHandler<Person>(Person.class);
// Execute the SQL statement with one replacement parameter and
// return the results in a new Person object generated by the BeanHandler.
Person p = run.query(
"SELECT * FROM Person WHERE name=?", h, "John Doe");
这次我们将使用从BeanListHandler从ResultSet获取所有行,并把它们变成javabean列表。
QueryRunner run = new QueryRunner(dataSource);
// Use the BeanListHandler implementation to convert all
// ResultSet rows into a List of Person JavaBeans.
ResultSetHandler<List<Person>> h = new BeanListHandler<Person>(Person.class);
// Execute the SQL statement and return the results in a List of
// Person objects generated by the BeanListHandler.
List<Person> persons = run.query("SELECT * FROM Person", h);
定制RowProcessor
每个提供ResultSetHandler实现都接受一个RowProcessor来把行转换为对象。默认结果集处理器使用BasicRowProcessor实现,但是你可以实现一个可插入的定制版本。也许最常见的定制是实现toBean()方法来处理自定义数据库数据类型问题。
定制BeanProcessor
BasicRowProcessor使用BeanProcessor将结果集列转换成JavaBean属性。你可以子类化进行覆盖处理步骤来处理特定于应用程序的数据类型映射。提供的实现将数据类型转换委托给JDBC驱动程序。
BeanProcessor 映射列到bean属性。列名称必须匹配bean属性名,其中大小写不敏感。例如,列名称 firstname 在bean 中应该通过调用它的 setFirstName()方法来存储。然而,许多数据库列名包含的字符在Java方法的名字中不能使用或不常用的。你可以做以下这些列映射到bean属性:
- 在SQL中取别名与Java名称相匹配
- 子类化BeanProcessor覆盖mapColumnsToProperties()方法来剔除厌恶的的字符
依赖
DbUtils有意使用一个单独的jar发布,并且只依赖于一个标准的Java 1.6或更高版本的JRE。