在线程中创建然后使用JDBC语句的最佳设计

时间:2015-01-21 13:48:01

标签: java multithreading jdbc db2

我正在一个应用程序中工作,需要在足够长的时间内在DB2表中填充大量数据和各种数据。所以我在代码中进行了更改,以便在不同的线程中填充数据,比如

public class ThreadPopulator implements Runnable
{
    volatile private boolean isTaskCompleted;
    volatile private Connection db2Conn;
    volatile private List<Data> list;
    volatile private String srcLib;

    public ThreadPopulator(Connection db2Conn, List<Data> list, String srcLib)
    {
        this.db2Conn = db2Conn;
        this.list = list;
        this.srcLib = srcLib;
    }

    public void run()
    {
        try
        {
            isTaskCompleted = false;
            execute(srcLib, list);
        }
        catch (Throwable e)
        {
        }
    }

    synchronized private void execute(String srcLib, List<Data> list)
    {
        PreparedStatement stmt = null;
        int len = list.size();

        for (int i = 0; i < len; i++)
        {
            try 
            {
                if (stmt == null)
                    stmt =
                            db2Conn.prepareStatement("INSERT INTO DATA VALUES(?, ?, ?, ?)",
                                ResultSet.TYPE_SCROLL_INSENSITIVE,
                                ResultSet.CONCUR_UPDATABLE,
                                ResultSet.HOLD_CURSORS_OVER_COMMIT);

                Data data = list.get(i);

                stmt.setString(1, srcLib);
                stmt.setString(2, "VV");
                stmt.setDouble(3, data.getSeq());
                stmt.setInt(4, data.getDate());

                stmt.addBatch();

                if ((i + 1) % 5000 == 0)
                    stmt.executeBatch(); // Execute every 5000 items.
            }
            catch (Exception e)
            {
            }
        }

        try
        {
            if (len > 0)
                stmt.executeBatch();  //for remaining records
        }
        catch (Exception e)
        {
        }
        finally
        {
            stmt.close();
            if (list != null) list.clear();
            isTaskCompleted = true;
        }
    }

    public static ThreadPopulator insert(Connection db2Conn, ArrayList<Data> list, String srcLib)
    {
        ThreadPopulator populator = new ThreadPopulator(db2Conn, srcLib);
        Thread thread = new Thread(populator);
        thread.start();
        return populator;
    }
}

然后我收到错误: DB2 SQL错误:SQLCODE = -805,SQLSTATE = 51002,SQLERRMC = NULLID.SYSLH21E 。意味着已打开语句的数量超过了大约13K的限制,因此我进行了一些日志记录以查看正在创建的语句数量(通过在prepareStatement()上递增一个静态计数器并通过递减close()),并且发现没有递减是发生,因为没有调用close(),总语句数达到22K。

所以我最后做了一些更改来创建一个静态语句对象,并在所有线程中使用该实例作为

private static PreparedStatement stmt = null;
public static void createStatement(Connection db2Conn)
    {
        try
        {
            if (stmt == null)
            {
                stmt =
                            db2Conn.prepareStatement("INSERT INTO DATA VALUES(?, ?, ?, ?)",
                                ResultSet.TYPE_SCROLL_INSENSITIVE,
                                ResultSet.CONCUR_UPDATABLE,
                                ResultSet.HOLD_CURSORS_OVER_COMMIT);
            }
        }
        catch (Exception e)
        {
        }
    }

现在一切正常。但作为Java开发人员,我对这种技术并不满意。即创建一个静态变量,然后在所有线程中使用该对象。

  

你能否告诉我什么是最好的设计   在线程中创建/使用语句,它也适用于我的情况   好。

提前致谢。

1 个答案:

答案 0 :(得分:2)

这些情况下的常见做法是使用某种connection pool;数据库驱动程序需要实现此功能。您可以在IBM的DB2 documentation找到有关DB2实现的信息。