如何在oracle11g中使用dbUtils获取CLOB列?

时间:2017-03-27 12:38:51

标签: java xml database oracle11g clob

我可以从数据库中获取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对象?

1 个答案:

答案 0 :(得分:2)

问题不是Apache Commons DbUtils的问题,而是涉及CLOB的一般问题。

通常,在执行返回CLOB值的查询时,JDBC驱动程序仅在获取行时加载CLOB值的一部分。在你的情况下,似乎它获取大约32K字符。对于小CLOB值,这将保存数据库的往返以获取值。但是,如果值较大,则驱动程序不会获取整个值,并且您需要对数据库进行后续调用以获取CLOB的其余部分。

在您的情况下,似乎在您上面提供的代码运行后会发生这种情况。此时,数据库连接已关闭,因此读取剩余的CLOB数据为时已晚,因此您会收到有关已关闭连接的异常。

更改此选项的一种方法是替换与DbUtils一起使用的默认行处理器。以下版本预先获取CLOB值并将其存储为字符串。根据{{​​3}},在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())