【问题标题】:How to fetch a CLOB column using dbUtils in oracle11g?如何在 oracle11g 中使用 dbUtils 获取 CLOB 列?
【发布时间】:2017-08-20 04:18:10
【问题描述】:

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

【问题讨论】:

    标签: java xml database oracle11g clob


    【解决方案1】:

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

    通常,在执行返回 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())

    【讨论】:

    • 完美解决方案,我可以获取大型 XML 文件,并且可以直接获取 String 对象而不是 CLOB。非常感谢卢克伍德沃德。
    猜你喜欢
    • 2012-02-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 2018-01-25
    • 2020-10-15
    相关资源
    最近更新 更多