【问题标题】:Java - JDBC - DB2 - "CLI0129E No more handles"Java - JDBC - DB2 - “CLI0129E 没有更多句柄”
【发布时间】:2016-05-27 03:59:56
【问题描述】:

这几天我一直在想这件事,现在来这里寻求一些帮助/想法

服务器:Solaris JDK:1.6 数据库:DB2

场景:

运行批处理作业,它有大约 6000 多条记录,但是当达到大约 2740 条记录时,出现以下错误 COM.ibm.db2.jdbc.DB2Exception: [IBM][CLI Driver] CLI0129E 没有更多句柄。 SQLSTATE=HY014

这是批处理作业,没有连接池,但看到代码使用“COM.ibm.db2.jdbc.DB2DataSource”

我已经完成了流程中的每一段代码,每个方法最终都使用 .close() 关闭了所有数据库资源。

在线寻找“不再有句柄”建议从释放方法中调用或增加 CLIPKG(这意味着性能开销)

在 Solaris 上没有任何工具来监视服务器上打开的连接等。更难,因为它不是游泳池。

有没有人遇到过这样的问题,或者可以帮助我解决下一步的问题。

每次处理一行时调用的示例代码(目前大约 3000 行):

Connection conn = null;
        PreparedStatement prepStmtSeq = null;
        PreparedStatement prepStmt = null;

        try 
        {
            LOG.info("DocumentDAO::createDocuments 37");
            conn = getConnection();

            prepStmtSeq = conn.prepareStatement(getSqlStmt("getNextDocumentId"));
            prepStmt = conn.prepareStatement(getSqlStmt("createDocument"));

            LOG.info("DocumentDAO::createDocuments 43");

            for (Document document: documents) {
                ResultSet resultsSeq = null;
                PreparedStatement prepStmtType = null;
                try {
                    resultsSeq = prepStmtSeq.executeQuery();
                    LOG.info("DocumentDAO::createDocuments 50");
                    resultsSeq.next();
                    LOG.info("DocumentDAO::createDocuments 52");
                    document.setDocumentId(resultsSeq.getLong(1));
                    prepStmt.setLong(1, document.getDocumentId());
                    prepStmt.setString(2, document.getCorrelationId());
                    prepStmt.setShort(3, document.getDocumentTypeCd());
                    prepStmt.setShort(4, document.getDocumentStatusCd());
                    prepStmt.setTimestamp(5, document.getCreatedDate());
                    prepStmt.setString(6, document.getCreatedBy());
                    LOG.info("DocumentDAO::createDocuments 60");
                    prepStmt.executeUpdate();
                    LOG.info("DocumentDAO::createDocuments 62");
                    if (document instanceof ScannedDocument) {
                        ScannedDocument scannedDocument = (ScannedDocument)document;
                        LOG.info("DocumentDAO::createDocuments 65");
                        prepStmtType = conn.prepareStatement(getSqlStmt("createScannedDocument"));
                        prepStmtType.setLong(1, scannedDocument.getDocumentId());
                        prepStmtType.setDate(2, scannedDocument.getScannedDate());
                        prepStmtType.setString(3, scannedDocument.getDrn());
                        prepStmtType.executeUpdate();
                        LOG.info("DocumentDAO::createDocuments 71");
                    }
                }
                finally 
                {
                    LOG.info("DocumentDAO::createDocuments 76");
                    if (prepStmtType != null) 
                    {
                        prepStmtType.close();

                    }
                    if (resultsSeq != null) 
                    {
                        resultsSeq.close();

                    }
                    LOG.info("DocumentDAO::createDocuments 87");
                }
            }
        }
        catch (SQLException ex) 
        {
            String[] message = {ex.getMessage(), getClass().getName()};
            throw new DataAccessException("SQLCode." + ex.getErrorCode(), message, ex);
        }
        finally 
        {
            try 
            {
                LOG.info("DocumentDAO::createDocuments 100");
                if (prepStmtSeq != null) 
                {
                    prepStmtSeq.close();
                }
                if (prepStmt != null) 
                {
                    prepStmt.close();
                }
                if (conn != null) 
                {
                    conn.close();
                }
                LOG.info("DocumentDAO::createDocuments 113");
            }
            catch (SQLException ex) 
            {
                String[] message = {ex.getMessage(), getClass().getName()};
                throw new DataAccessException("SQLCode." + ex.getErrorCode(), message, ex);
            }
        }

【问题讨论】:

  • 发布源代码或至少一个描述您的问题的片段将帮助其他人帮助您..
  • 道歉。在帖子中添加了上面的代码。

标签: java jdbc db2


【解决方案1】:

对不起,我的朋友回复晚了...

您正在使用两个 PreparedStatements

  • prepStmtSeq
  • prepStmt

当您执行第一个 PreparedStatement(prepStmtSeq) 时,您会得到一个 resultSet 并且与数据库的连接已关闭.. 所以当下一个 PreparedStatement(prepStmt) 执行时,连接被关闭..

所以试试这个解决方案,然后回复我....

class Database 
{
public  Connection conn;
private  Statement stat;
//Creating and establishing connection with database...
//Called at first in each method because connection is opened only when required...
public Database() 
{
    try
    {
        Class.forName("org.sqlite.JDBC");  
        conn = DriverManager.getConnection("jdbc:sqlite:South2Books.db"); 
        stat = conn.createStatement(); 
    }
    catch(Exception e)
    {}
}

public synchronized PreparedStatement prepareStatement(String s)
{
    try 
    {
        PreparedStatement prep= conn.prepareStatement(s);
        System.out.println("CONN "+conn.isClosed());
        if(conn.isClosed())
        {
            System.out.println("CONNECTION RECREATED");
            conn = DriverManager.getConnection("jdbc:sqlite:South2Books.db"); 
        }
        return prep;

    } 
    catch (SQLException e) 
    {e.printStackTrace();}
    return null;
}
// If you want to do other transactions
public synchronized void execute(String s)
{
    try {
        stat.execute(s);
    } catch (SQLException e) 
    {e.printStackTrace();}
}
public synchronized void executeUpdate(String s)
{
    try {
        stat.execute(s);
    } catch (SQLException e) 
    {e.printStackTrace();}
}
public synchronized ResultSet executeQuery(String s)
{
    try 
    {
        return stat.executeQuery(s);
    } 
    catch (SQLException e) 
    {e.printStackTrace();}
    return null;
}
public void close()
{
    try
    {
        if(conn.isClosed()==false)
        {
            stat.close();
            conn.close();
        }
    }
    catch(Exception e)
    {e.printStackTrace();}
}
}

这种方法比前一种方法要好得多,因为您创建了一个类数据库对象来执行所有事务..(面向对象编程).. 即使你多线程这也不会有问题..

所以现在您需要更改的三个语句是:

prepStmtSeq = db.prepareStatement(getSqlStmt("getNextDocumentId"));
prepStmt = db.prepareStatement(getSqlStmt("createDocument"));
prepStmtType = db.prepareStatement(getSqlStmt("createScannedDocument"));

【讨论】:

  • 感谢 Vaibhav。我正在使用一个自定义框架静态方法。但是,仍在查看代码。在 prepStmtType.executeUpdate(); 之后调用 close() 是否有任何具体原因? ??
  • 没有连接池实现,而是普通的旧 JDBC 并试图处理 2700 多行。
猜你喜欢
  • 1970-01-01
  • 2016-10-17
  • 2013-11-25
  • 1970-01-01
  • 2011-10-31
  • 2015-01-04
  • 1970-01-01
  • 2017-08-23
  • 2013-12-24
相关资源
最近更新 更多