Пул соединений с использованием общих DBCP и DBUtils Apache и параллелизма

Я изучаю параллелизм при выполнении нескольких запросов в разных потоках. Я использую Apache DBCP и DBUtils не потому, что хочу усложнить себе жизнь, а потому, что они должны гарантировать правильную обработку запросов и, следовательно, параллелизм.

Однако даже с вышеупомянутыми классными инструментами я получаю:

Error : org.h2.jdbc.JdbcSQLException: Das Objekt wurde bereits geschlossen
The object is already closed [90007-148]
Error : java.lang.NullPointerException

Это та же самая ошибка, которую я получил также при использовании объектов базы данных и соединения вручную. Это происходит один раз на каждые 5-6 запусков программы, но это просто игрушечная программа, в реальном приложении такие ошибки будут появляться постоянно.

Ниже моего примера кода

DatatTransaction.java

import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbcp.BasicDataSource;

public class DataTransaction
{
    private final static String username = "";
    private final static String password = "";
    private final static String url = "db" + File.separator + "persondb;create=true";
    public static Connection connection = null;
    public static BasicDataSource dataSource;

    public DataTransaction(boolean setCon)
    {
        try
        {
            setConnectionTest();
        }
        catch (Exception e)
        {
            System.out.println("Error in Connection:" + e.toString());
        }
    }

    public final void setConnectionTest() throws SQLException
    {
        try
        {
            if (dataSource == null)
            {
                dataSource = new BasicDataSource();
                String driver = "org.h2.Driver";
                try
                {
                    dataSource.setDriverClassName(driver);
                    dataSource.setUrl("jdbc:h2:"+url);
                    dataSource.setUsername(username);
                    dataSource.setPassword(password);
                    dataSource.setMaxActive(100);
                    dataSource.setMaxWait(10000);
                    dataSource.setMaxIdle(10);
                    if (connection == null || connection.isClosed())
                    {
                        connection = dataSource.getConnection();
                    }
                }
                catch (SQLException e)
                {
                    System.out.println("Could not connect to the database msg :" + e.getMessage());
                }
            }
            else
            {
                connection = dataSource.getConnection();
            }
        }
        catch (Exception e)
        {
            System.out.println("open connection exception" + e);
        }
    }
}

и DBTest2.java

package dbtest;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class DBTest2
{

    public static void main(String[] args)
    {
        try
        {
            new Thread(db1).start();
            new Thread(db2).start();
        }
        catch (Exception e)
        {
            System.out.println("MM : Error : " + e);
        }
    }
    private static Runnable db1 = new Runnable()
    {
        public void run()
        {
            try
            {
                for (int i = 0; i < 50; i++)
                {
                    DBTest2 dBTest = new DBTest2();
                    List<Object[]> list1 = dBTest.DB1();
                    for (Object[] object : list1)
                    {
                        System.out.println("DB1 : FirstName : " + object[0] + " Lastname: " + object[1]);
                    }
                }
            }
            catch (Exception e)
            {
                System.out.println("Error : " + e);
            }
        }
    };

    private static Runnable db2 = new Runnable()
    {
        public void run()
        {
            try
            {
                for (int i = 0; i < 50; i++)
                {
                    DBTest2 dBTest = new DBTest2();
                    List<Object[]> list = dBTest.DB2();
                    for (Object[] object : list)
                    {
                        System.out.println("DB2 : FirstName : " + object[0] + " Lastname: " + object[1]);
                    }
                }
            }
            catch (Exception e)
            {
                System.out.println("Error : " + e);
            }
        }
    };

    public List<Object[]> DB1()
    {
        try
        {
            DataTransaction dt = new DataTransaction(true);
            Connection conn = dt.connection;
            Statement statement = conn.createStatement();
            ResultSet rs = statement.executeQuery("select NAME,SURNAME from PERSON");
            ResultSetMetaData rsmd = rs.getMetaData();
            int dataCnt = rsmd.getColumnCount();
            List<Object[]> list = new ArrayList<Object[]>();
            while (rs.next())
            {
                Object[] data = new Object[dataCnt];
                for (int i = 0; i < dataCnt; i++)
                {
                    data[i] = rs.getString(i + 1);
                }
                list.add(data);
            }
            conn.close();
            return list;
        }
        catch (Exception e)
        {
            System.out.println("Error : " + e);
            return null;
        }
    }

    public List<Object[]> DB2()
    {
        try
        {
            DataTransaction dt = new DataTransaction(true);
            Connection conn = dt.connection;
            Statement statement = conn.createStatement();
            ResultSet rs = statement.executeQuery("select NAME,SURNAME from PERSON");
            ResultSetMetaData rsmd = rs.getMetaData();
            int dataCnt = rsmd.getColumnCount();
            List<Object[]> list = new ArrayList<Object[]>();
            while (rs.next())
            {
                Object[] data = new Object[dataCnt];
                for (int i = 0; i < dataCnt; i++)
                {
                    data[i] = rs.getString(i + 1);
                }
                list.add(data);
            }
            conn.close();
            return list;
        }
        catch (Exception e)
        {
            System.out.println("Error : " + e);
            return null;
        }
    }
}

comment
Обратите внимание, что если я прокомментирую connection.close(); Я получаю другую ошибку: открыть соединение exceptionorg.apache.commons.dbcp.SQLNestedException: не удается установить соединение, ошибка пула Тайм-аут ожидания ожидания объекта бездействия   -  person dendini    schedule 13.06.2013


Ответы (1)


Вам следует ознакомиться с подводными камнями дерби. общие подводные камни, тот, который вас интересует, это:

«Выполнение оператора автоматически закрывает любой существующий открытый набор результатов, сгенерированный более ранним выполнением этого оператора. Если потоки совместно используют операторы, один поток может закрыть другой набор результатов. Во многих случаях проще назначить каждый поток отдельному соединению».

Итак, проблема с вашим кодом заключается в DatatTransaction.java, измените код, удалив соединение со статической переменной, и добавьте этот метод:

    public final Connection getConnection()
{
    Connection conn = null;
    try
    {
        conn = dataSource.getConnection();
    }
    catch (SQLException e)
    {
        System.out.println("Could not connect to the database msg :" + e.getMessage());
    }
    return conn;
}

Теперь это больше не будет вызывать никаких проблем (кстати, если вы прокомментируете System.out.println() в своем примере, вы увидите более быстрые и частые ошибки параллелизма, которые в противном случае смягчаются временем, необходимым для печати на консоль).

Что касается «exceptionorg.apache.commons.dbcp.SQLNestedException: не удается получить соединение, ошибка пула. Тайм-аут ожидания объекта ожидания», это потому, что вы неправильно закрываете ресурсы, комментируя методы close(), поэтому вы быстро исчерпали соединения в пуле.

person sarah.ferguson    schedule 13.06.2013