[Программирование, Java] Работа с БД с помощью JAVA и JDBC

Автор Сообщение
news_bot ®

Стаж: 6 лет 3 месяца
Сообщений: 27286

Создавать темы news_bot ® написал(а)
25-Июн-2021 15:33


При работе с БД вы наверняка прибегали к использованию Python и ODBC. Это хорошие инструменты для работы с большими данными, но они сталкиваются с ограничением производительности при работе с ОЧЕНЬ большими объёмами данных. Например, обработка таблицы с несколькими миллионами строк может занять несколько десятков часов, что может быть критично. В такой ситуации разумно посмотреть в сторону Java и JDBC – обёртку вокруг интерфейса ODBC для Java. Данное решение будет работать ощутимо быстрее, чем аналогичное на python с использованием ODBC, что в некоторых ситуациях является крайне необходимым. Конкретный пример обработки данных мы рассмотрим в следующей статье. А сейчас рассмотрим работу с JDBC, а также напишем модуль для упрощения работы с ним.Создадим новый проект с использованием maven и включим в pom.xml интересующие нас пакеты для подключения к MS SQL: jdbc, mssql-jdbc, mssql-jdbc_auth.Дождёмся загрузки пакетов и начнём писать код.
import java.sql.*; // Импорт пакета для работы с базой
public class MainClass {
    public static void main(String[] args){
    String server = "localhost"; // Адрес сервера БД
    String dbName = "testDB"; // имя БД
    String user = "user"; // Имя пользователя БД
    String password = "password"; // пароль пользователя БД
        Connection conn = null; // Объявление переменной подключения
    // Формирование строки подключения и переменной с используемым драйвером
        String connString = "jdbc:sqlserver://" + server + ";databaseName=" + dbName + ";";
        String driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
    // Объявление переменной для выполнения запросов
        Statement stmt;
        try {
      // Загрузка драйвера и инициализация подключения
            Class.forName(driver);
            conn = DriverManager.getConnection(connString, user, password);
      // Формирование строки запроса
            String query = "SELECT * FROM [testTable]";
      // Инициализация обработчика запросов и указание ограничения на количество строк,
      // которые одновременно находятся в ОЗУ
            stmt = conn.createStatement();
      stmt.setFetchSize(100);
      // Выполнение запроса
            ResultSet responce = stmt.executeQuery(query);
      while(responce.next()) {
        // Перебор всех строк в таблице и вывод первого столбца каждой строки
        System.out.println(responce.getString(1));
      }
            conn.close(); // Закрытие подключения
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Для использования внутренней проверки безопасности (подключение по УЗ вместо логина и пароля), необходимо добавить в строку подключения параметр integratedSecurity со значением true и при инициализации подключения убрать из параметров имя пользователя и пароль.Теперь же напишем модуль, сокращающий количество кода, необходимого для подключения и выполнения запросов к БД до минимума.Создадим новый класс DBC, конструктор которого должен выполнять следующие задачи: — получать необходимые для подключения данные; — инициализировать соответствующие поля; — проверять возможность подключения по переданным данным; — при необходимости сообщать о неверно введённых данных и/или недоступности сервера. А также конструктор необходимо перегрузить для возможности обрабатывать все возможные варианты подключения.
package DataBaseTools;
import java.sql.*;
public class DBC {
    private final String serverUrl; // Адрес сервера баз данных
    private final String dbName; // Имя базы данных
    private String driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; // Используемый драйвер
    private String user = ""; // Имя пользователя базы данных
    private String password = ""; // Пароль пользователя базы данных
    private final boolean readyToWork; // Флаг готовности класса к работе с базы данных
    /**
     * Конструктор для работы со встроенной системой проверки безопасности.
     *
     * @param serverUrl Адрес сервера баз данных
     * @param dbName    Имя базы данных
     */
    DBC(String serverUrl, String dbName) {
        this.serverUrl = serverUrl;
        this.dbName = dbName;
        readyToWork = checkConnection();
    }
    /**
     * Конструктор для работы со встроенной системой проверки безопасности и с указанным драйвером.
     *
     * @param serverUrl Адрес сервера баз данных
     * @param dbName    Имя базы данных
     * @param driver    Используемый драйвер. По умолчанию <code>com.microsoft.sqlserver.jdbc.SQLServerDriver</code>
     */
    DBC(String serverUrl, String dbName, String driver) {
        this.serverUrl = serverUrl;
        this.dbName = dbName;
        this.driver = driver;
        readyToWork = checkConnection();
    }
    /**
     * Конструктор для работы с использованием имени и пароля пользователя базы данных.
     *
     * @param serverUrl Адрес сервера баз данных
     * @param dbName    Имя базы данных
     * @param user      Имя пользователя
     * @param password  Пароль
     */
    DBC(String serverUrl, String dbName, String user, String password) {
        this.serverUrl = serverUrl;
        this.dbName = dbName;
        this.user = user;
        this.password = password;
        readyToWork = checkConnection();
    }
    /**
     * Конструктор для работы с использованием имени и пароля пользователя базы данных и указанием драйвера.
     *
     * @param serverUrl Адрес сервера баз данных
     * @param dbName    Имя базы данных
     * @param user      Имя пользователя
     * @param password  Пароль
     * @param driver    Используемый драйвер. По умолчанию <code>com.microsoft.sqlserver.jdbc.SQLServerDriver</code>
     */
    DBC(String serverUrl, String dbName, String user, String password, String driver) {
        this.serverUrl = serverUrl;
        this.dbName = dbName;
        this.user = user;
        this.password = password;
        this.driver = driver;
        readyToWork = checkConnection();
    }
}
Обратите внимание, что практически все поля класса имеют модификатор final, что сделано для возможности работы одного экземпляра только с одной базой. Далее напишем приватный метод checkConnection, который будет создавать тестовое подключение и при отсутствии ошибок возвращать true (иначе false), которое записывается в поле readyToWork, выступающее флагом успешности/не успешности инициализации экземпляра класса. Также напишем ещё один приватный метод createConnection, создающий и возвращающий новое подключение. Он нужен для избегания ненужного дублирования кода.
/**
* Создаёт объект подключения.
*
* @return Объект подключения.
*/
private Connection createConnection() {
    // Формирование строки подключения
    String connStr = "jdbc:sqlserver://" + this.serverUrl + ";databaseName=" + this.dbName + ";";
    try {
        // Установка драйвера
        Class.forName(driver);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
        return null;
    }
    Connection conn;
    if (this.user.equals("") && this.password.equals("")) {
        // Подключение с встроенной проверкой безопасности
        connStr += "integratedSecurity=true;";
        try {
            conn = DriverManager.getConnection(connStr);
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    } else {
        // Подключение по имени и паролю пользователя
        try {
            conn = DriverManager.getConnection(connStr, user, password);
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }
    return conn;
}
/**
* Проверяет возможность установления подключения с сервером баз данных.
*
* @return true - подключение успешно.
*/
private boolean checkConnection() {
    Connection testConnection = createConnection();
    if (testConnection == null) {
        System.out.println("Can't connect to server. Check throws & url/dbName/username/password.\n" +
                "*IntegratedSecurity option require sqljdbc_auth.dll in java.library.path.");
        return false;
    } else {
        try {
            testConnection.close();
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}
Теперь перейдём к выполнению запросов. Создадим публичный класс execQuery с единственным параметром – текстом запроса. Возвращать метод будет экземпляр ResultSet, содержащий результаты выполнения запроса.
/**
* Выполняет любой запрос переданный в параметре
*
* @param query Текст запроса
* @return ResultSet с результатами работы запроса
*/
public ResultSet execQuery(String query) {
    if (!readyToWork) {
        System.out.println("DBC not ready to work! Abort:execQuerySelected");
        return null;
    }
    Connection conn = createConnection();
    Statement stmt;
    try {
        assert conn != null;
        stmt = conn.createStatement();
        stmt.setFetchSize(100);
        return stmt.executeQuery(query);
    } catch (SQLException e) {
        e.printStackTrace();
        System.out.println("Something wrong... Check your query text.");
        return null;
    }
}
На этом моменте можно считать модуль минимально завершённым. Заменим первоначальный код работы с базой из начала статьи на следующий:
package DataBaseTools;
import java.sql.ResultSet;
import java.sql.SQLException;
public class MainClass {
    public static void main(String[] args) throws SQLException {
        // Создание нового экземпляра
        DBC dbc = new DBC("localhost", "testDB");
        // Выполнение запроса
        ResultSet response = dbc.execQuery ("select * from testTable");
        // Вывод результата работы запроса на экран
        if (response == null) {
            System.out.println("NULL");
        } else {
            while (response.next()) {
                System.out.println(response.getString(1));
            }
        }
    }
}
Как видим, подключение и выполнение запроса сократились до 2х строк, что упрощает дальнейшее использование модуля.В заключении хочется сказать: нет ничего плохого в быстром написании небольшого скрипта на Python, который обработает небольшие объёмы данных из БД, но при критичности времени, затрачиваемого на эту работу, более оптимальное решение – Java с JDBC.
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_programmirovanie (Программирование), #_java, #_java, #_jdbc, #_jdbc_connection, #_programmirovanie (
Программирование
)
, #_java
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 13-Май 15:28
Часовой пояс: UTC + 5