如何在 oracle11g 中使用 dbUtils 获取 CLOB 列?
How to fetch a CLOB column using dbUtils in oracle11g?
我可以从数据库中获取 CLOB 值,但如果值大于 32k,则会出现错误:
java.sql.SQLRecoverableException: Closed Connection
at oracle.sql.CLOB.getDBAccess(CLOB.java:1510)
at oracle.sql.CLOB.getSubString(CLOB.java:317)
代码:
List<Map<String, Object>> resultListMap = null;
try {
new DbUtilsBeanListHandlerImpl();
DbUtils.loadDriver(driver);
Properties connectionProperties = new Properties();
connectionProperties.put("user", userName);
connectionProperties.put("password", password);
conn = DriverManager.getConnection(url, connectionProperties);
QueryRunner query = new QueryRunner();
resultListMap = query.query(conn, dbQuery, new MapListHandler());
} catch (SQLException se) {
logger.error("SQLException to connect Database "+se.getMessage(), se);
} finally {
DbUtils.closeQuietly(conn);
}
如何使用 dbUtils 获取大于 32k 的 CLOB 对象?
问题与其说是 Apache Commons DbUtils 的问题,不如说是涉及 CLOB 的一般问题。
通常,当执行returns CLOB 值的查询时,JDBC 驱动程序在获取行时只会加载部分CLOB 值。在您的情况下,它似乎获取了大约 32K 个字符。对于小的 CLOB 值,这节省了到数据库的往返以获取该值。但是,如果该值较大,驱动程序将不会获取整个值,您将需要对数据库进行后续调用以获取 CLOB 的其余部分。
在您的情况下,这似乎发生在您上面提供的代码运行之后。此时,数据库连接已关闭,因此读取其余 CLOB 数据为时已晚,因此您会收到有关已关闭连接的异常。
更改此设置的一种方法是替换与 DbUtils 一起使用的默认行处理器。以下版本预取 CLOB 值并将它们存储为字符串。根据 this answer,对 CLOB 值调用 ResultSet.getString()
足以获取整个值:
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.dbutils.BasicRowProcessor;
public class ClobAwareRowProcessor extends BasicRowProcessor {
@Override
public Map<String, Object> toMap(ResultSet resultSet) throws SQLException {
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
int columnCount = resultSetMetaData.getColumnCount();
Map<String, Object> map = new HashMap<>();
for (int index = 1; index <= columnCount; ++index) {
String columnName = resultSetMetaData.getColumnName(index);
Object object = resultSet.getObject(index);
if (object instanceof Clob) {
object = resultSet.getString(index);
}
map.put(columnName, object);
}
return map;
}
}
要使用,请将 new MapListHandler()
替换为 new MapListHandler(new ClobAwareRowProcessor())
。
我可以从数据库中获取 CLOB 值,但如果值大于 32k,则会出现错误:
java.sql.SQLRecoverableException: Closed Connection
at oracle.sql.CLOB.getDBAccess(CLOB.java:1510)
at oracle.sql.CLOB.getSubString(CLOB.java:317)
代码:
List<Map<String, Object>> resultListMap = null;
try {
new DbUtilsBeanListHandlerImpl();
DbUtils.loadDriver(driver);
Properties connectionProperties = new Properties();
connectionProperties.put("user", userName);
connectionProperties.put("password", password);
conn = DriverManager.getConnection(url, connectionProperties);
QueryRunner query = new QueryRunner();
resultListMap = query.query(conn, dbQuery, new MapListHandler());
} catch (SQLException se) {
logger.error("SQLException to connect Database "+se.getMessage(), se);
} finally {
DbUtils.closeQuietly(conn);
}
如何使用 dbUtils 获取大于 32k 的 CLOB 对象?
问题与其说是 Apache Commons DbUtils 的问题,不如说是涉及 CLOB 的一般问题。
通常,当执行returns CLOB 值的查询时,JDBC 驱动程序在获取行时只会加载部分CLOB 值。在您的情况下,它似乎获取了大约 32K 个字符。对于小的 CLOB 值,这节省了到数据库的往返以获取该值。但是,如果该值较大,驱动程序将不会获取整个值,您将需要对数据库进行后续调用以获取 CLOB 的其余部分。
在您的情况下,这似乎发生在您上面提供的代码运行之后。此时,数据库连接已关闭,因此读取其余 CLOB 数据为时已晚,因此您会收到有关已关闭连接的异常。
更改此设置的一种方法是替换与 DbUtils 一起使用的默认行处理器。以下版本预取 CLOB 值并将它们存储为字符串。根据 this answer,对 CLOB 值调用 ResultSet.getString()
足以获取整个值:
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.dbutils.BasicRowProcessor;
public class ClobAwareRowProcessor extends BasicRowProcessor {
@Override
public Map<String, Object> toMap(ResultSet resultSet) throws SQLException {
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
int columnCount = resultSetMetaData.getColumnCount();
Map<String, Object> map = new HashMap<>();
for (int index = 1; index <= columnCount; ++index) {
String columnName = resultSetMetaData.getColumnName(index);
Object object = resultSet.getObject(index);
if (object instanceof Clob) {
object = resultSet.getString(index);
}
map.put(columnName, object);
}
return map;
}
}
要使用,请将 new MapListHandler()
替换为 new MapListHandler(new ClobAwareRowProcessor())
。