本页提供了一些示例,说明如何使用Dbutils。
DbUtils是一个非常小的类库,因此不需要很长时间就可以遍历每个类的javadocs。DbUtils中的核心类/接口是QueryRunner和ResultSetHandler。您不需要了解任何其他DbUtils类就可以从使用该库中获益。下面的示例演示了如何将这些类一起使用。
// 创建ResultSetHandler实现以将第一行转换为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;
}
};
// 创建一个QueryRunner,该QueryRunner将使用来自给定DataSource的连接
QueryRunner run = new QueryRunner(dataSource);
// 执行查询并从处理程序返回结果
Object[] result = run.query(
"SELECT * FROM Person WHERE name=?", h, "John Doe");
您也可以使用java.sql.Connection对象而不是DataSource来执行上一个查询。请注意,在本例中,您负责关闭Connection。
ResultSetHandler<Object[]> h = ... // 定义与上例相同的处理程序
// 没有数据源,因此我们必须手动处理连接
QueryRunner run = new QueryRunner();
Connection conn = ... // 打开连接
try{
Object[] result = run.query(
conn, "SELECT * FROM Person WHERE name=?", h, "John Doe");
// 用结果做点什么
} finally {
// 使用这个helper方法,这样我们就不必检查null
DbUtils.close(conn);
}
您不仅可以从数据库中获取数据,还可以插入或更新数据。以下示例将首先将一个人插入数据库,然后更改该人的身高。
QueryRunner run = new QueryRunner( dataSource );
try
{
// 执行SQL更新语句并返回进行的插入次数
int inserts = run.update( "INSERT INTO Person (name,height) VALUES (?,?)",
"John Doe", 1.82 );
// 前一行使用varargs和自动装箱来简化代码
// 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
{
// 为更新调用创建Callable
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
}
// 稍后(或在另一个线程中)
try
{
// 获取更新结果
Integer updates = executor.take().get();
} catch(InterruptedException ie) {
// Handle it
}
在上面的例子中,我们实现了ResultSetHandler接口,将ResultSet的第一行转换为Object[]。这是一个相当通用的实现,可以在许多项目中重用。认识到这一点,DbUtils在org.apache.commons.butils.handlers包中提供了一组ResultSetHandler实现,用于执行到数组、Maps和JavaBeans的常见转换。每个实现都有一个版本,只转换第一行,另一个版本转换ResultSet中的所有行。
我们将从一个使用BeanHandler从ResultSet中提取一行并将其转换为JavaBean的示例开始。
QueryRunner run = new QueryRunner(dataSource);
// 使用BeanHandler实现将第一个ResultSet行转换为PersonJavaBean。
ResultSetHandler<Person> h = new BeanHandler<Person>(Person.class);
// 使用一个替换参数执行SQL语句,并在BeanHandler生成的新Person对象中返回结果。
Person p = run.query(
"SELECT * FROM Person WHERE name=?", h, "John Doe");
这一次,我们将使用BeanListHandler从ResultSet中获取所有行,并将它们转换为JavaBeans列表。
QueryRunner run = new QueryRunner(dataSource);
// 使用BeanListHandler实现将所有ResultSet行转换为Person JavaBeans列表
ResultSetHandler<List<Person>> h = new BeanListHandler<Person>(Person.class);
// 执行SQL语句并在BeanListHandler生成的Person对象列表中返回结果
List<Person> persons = run.query("SELECT * FROM Person", h);
所提供的每个ResultSetHandler实现都接受一个RowProcessor来将行实际转换为对象。默认情况下,处理程序使用BasicRowProcessor实现,但您可以实现一个自定义版本来插入。可能最常见的自定义是实现toBean()方法来处理自定义数据库数据类型问题。
BasicRowProcessor使用BeanProcessor将ResultSet列转换为JavaBean属性。您可以对处理步骤进行子类化和覆盖,以处理特定于应用程序的数据类型映射。所提供的实现将数据类型转换委托给JDBC驱动程序。
BeanProcessor将列映射到bean属性,如BeanProcessor.toBean() javadoc中所述。列名必须与bean的属性名称不区分大小写匹配。例如,firstname列将通过调用其setFirstName()方法存储在bean中。但是,许多数据库列名包含Java方法名中不能使用或通常不使用的字符。您可以执行以下操作之一将这些列映射到bean属性: