Пул соединений DBCP

Могу ли я спросить, будет ли приведенный ниже код правильно использовать пул соединений (DBCP)?

Мой служебный класс, предоставляющий BasicDataSource, показан ниже (почти идентичен примеру apache).

public class DatabaseUtility {

    private static BasicDataSource dataSource;

    public static BasicDataSource getDataSource(Properties prop) {

        if (dataSource == null)
        {
            BasicDataSource ds = new BasicDataSource();
            ds.setUrl("jdbc:oracle:thin:@"+ prop.getProperty("db") + ":" + prop.getProperty("dbPort") + "/" + 
                    prop.getProperty("dbService"));
            ds.setUsername(prop.getProperty("dbUser"));
            ds.setPassword(prop.getProperty("dbPassword"));


            ds.setMinIdle(5);
            ds.setMaxIdle(10);
            ds.setMaxOpenPreparedStatements(100);

            dataSource = ds;
        }
        return dataSource;
    }

Затем я использую вышеизложенное как:

public class MyClass {

    public static boolean isNew(Properties prop, String label) {

        Connection connection = null;
        PreparedStatement ps = null;

        try {
            BasicDataSource dataSource = DatabaseUtility.getDataSource(prop);
            connection = dataSource.getConnection();
            ps = connection.prepareStatement("Select * from my_table where LABEL = CAST( ? AS CHAR(35))");
            ps.setString(1, label);
            if (ps.executeQuery().isBeforeFirst()) {
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (ps != null)
                    ps.close();
                if (connection != null)
                    connection.close();
            } catch (SQLException e) {
                System.out.println("Error while closing resource :");
                e.printStackTrace();
            }
        }
        return true;
    }
}

Класс MyClass может использоваться несколькими порожденными потоками. Любые потенциальные проблемы с этими кодами, которые я не вижу?

Большое спасибо


person nullPointer    schedule 27.09.2018    source источник


Ответы (2)


Вы можете столкнуться с проблемами, если несколько разных потоков будут вызывать DatabaseUtility.getDataSource в первый раз. Вы можете получить несколько экземпляров вашего источника данных. Прочтите эту ссылку для поточно-ориентированной ленивой одноэлементной инициализации: https://www.geeksforgeeks.org/java-singleton-design-pattern-practices-examples

person Ivan    schedule 27.09.2018
comment
поэтому вы в основном предлагаете просто изменить объявление метода в классе DatabaseUtility, как показано ниже (например, сделать его синхронизированным?) public synchronized static BasicDataSource getDataSource(Properties prop) {... - person nullPointer; 27.09.2018
comment
@funkyjelly Метод создания synchronized — это решение с наихудшей производительностью. Я бы предпочел идиому класса держателя (реализация Билла Пью Синглтона из предоставленной ссылки) - person Ivan; 27.09.2018
comment
после небольшой проверки кажется, что BasicDataSource является потокобезопасным, поскольку (почти) все его переменные читаются/записываются синхронно. методы. issues.apache.org/jira/browse/DBCP-285 Меры, которые вы предлагаете, действительно необходимы? - person nullPointer; 27.09.2018
comment
@funkyjelly проблема, на которую я указал, может возникнуть, когда два потока вызывают BasicDataSource getDataSource() одновременно. Оба увидят этот datasource == null и создадут два экземпляра BasicDataSource. - person Ivan; 27.09.2018

если вы переключитесь на пул HikariCP, настройки проверки соединения будут выполнены автоматически. Взгляните на несколько ошибок в пулах, например:

person Karol Dowbecki    schedule 27.09.2018
comment
согласно документам DBCP, testOnBorrow по умолчанию имеет значение true. Видите ли вы какую-либо другую важную конфигурацию, которая может отсутствовать? Если я не ошибаюсь, у меня должно быть хорошо с настройкой по умолчанию. - person nullPointer; 27.09.2018
comment
@funkyjelly, вы правы, удалили эту часть ответа. Я не знаю, чем новый DBCP 2.5+ отличается от HikariCP. В старых версиях DBCP были некоторые проблемы, я добавил несколько ссылок, чтобы выделить проблему. - person Karol Dowbecki; 27.09.2018