Пакетная обработка в JDBC

Пакетная обработка в JDBC

1. Вступление

Java Database Connectivity (JDBC) - это Java API, используемый для взаимодействия с базами данных. Пакетная обработка группирует несколько запросов в один блок и передает их в одной сетевой поездке в базу данных.

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

Чтобы узнать больше о JDBC, вы можете ознакомиться с нашей вводной статьейhere.

2. Почему пакетная обработка?

Производительность и согласованность данных являются основными мотивами для пакетной обработки.

2.1. Улучшенная производительность

В некоторых случаях требуется вставить большой объем данных в таблицу базы данных. При использовании JDBC одним из способов достижения этого без пакетной обработки является последовательное выполнение нескольких запросов.

Давайте посмотрим на пример последовательных запросов, отправляемых в базу данных:

statement.execute("INSERT INTO EMPLOYEE(ID, NAME, DESIGNATION) "
 + "VALUES ('1','EmployeeName1','Designation1')");
statement.execute("INSERT INTO EMPLOYEE(ID, NAME, DESIGNATION) "
 + "VALUES ('2','EmployeeName2','Designation2')");

Эти последовательные вызовы увеличивают количество сетевых обращений к базе данных, что приводит к снижению производительности.

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

2.2. Согласованность данных

В определенных обстоятельствах данные должны быть помещены в несколько таблиц. Это приводит к взаимосвязанной транзакции, в которой важна последовательность отправляемых запросов.

Любые ошибки, возникающие во время выполнения, должны привести к откату данных, выдвинутых предыдущими запросами, если таковые имеются.

Давайте посмотрим на пример добавления данных в несколько таблиц:

statement.execute("INSERT INTO EMPLOYEE(ID, NAME, DESIGNATION) "
 + "VALUES ('1','EmployeeName1','Designation1')");
statement.execute("INSERT INTO EMP_ADDRESS(ID, EMP_ID, ADDRESS) "
 + "VALUES ('10','1','Address')");

Типичная проблема в вышеупомянутом подходе возникает, когда первый оператор завершается успешно, а второй - не выполняется. In this situation there is no rollback of the data inserted by the first statement, leading to data inconsistency.с

Мы можем добиться согласованности данных, распределив транзакцию между несколькими вставками / обновлениями и затем зафиксировав транзакцию в конце или выполнив откат в случае исключений, но в этом случае мы все равно повторно обращаемся к базе данных для каждого оператора.

3. Как сделать пакетную обработку

JDBC предоставляет два классаStatement иPreparedStatement для выполнения запросов к базе данных. Оба класса имеют собственную реализацию методовaddBatch() иexecuteBatch(), которые предоставляют нам функциональность пакетной обработки.

3.1. Пакетная обработка с использованиемStatement

С JDBC самый простой способ выполнять запросы к базе данных - через объектStatement.

Во-первых, используяaddBatch(), мы можем добавить все SQL-запросы в пакет, а затем выполнить эти SQL-запросы с помощьюexecuteBatch().

Тип возвратаexecuteBatch() - это массивint, указывающий, сколько записей было затронуто выполнением каждого оператора SQL.

Давайте посмотрим на пример создания и выполнения пакета с помощью Statement:

Statement statement = connection.createStatement();
statement.addBatch("INSERT INTO EMPLOYEE(ID, NAME, DESIGNATION) "
 + "VALUES ('1','EmployeeName','Designation')");
statement.addBatch("INSERT INTO EMP_ADDRESS(ID, EMP_ID, ADDRESS) "
 + "VALUES ('10','1','Address')");
statement.executeBatch();

В приведенном выше примере мы пытаемся вставить записи в таблицыEMPLOYEE иEMP_ADDRESS, используяStatement. Мы можем видеть, как SQL-запросы добавляются в пакет для выполнения.

3.2. Пакетная обработка с использованиемPreparedStatement

PreparedStatement - еще один класс, используемый для выполнения SQL-запросов... Он позволяет повторно использовать операторы SQL и требует от нас установки новых параметров для каждого обновления / вставки.

Давайте посмотрим на пример с использованиемPreparedStatement.. Сначала мы настроим оператор, используя запрос SQL, закодированный какString:

String[] EMPLOYEES = new String[]{"Zuck","Mike","Larry","Musk","Steve"};
String[] DESIGNATIONS = new String[]{"CFO","CSO","CTO","CEO","CMO"};

String insertEmployeeSQL = "INSERT INTO EMPLOYEE(ID, NAME, DESIGNATION) "
 + "VALUES (?,?,?)";
PreparedStatement employeeStmt = connection.prepareStatement(insertEmployeeSQL);

Затем мы перебираем массив значенийString и добавляем новый настроенный запрос в пакет.

После завершения цикла мы выполняем пакет:

for(int i = 0; i < EMPLOYEES.length; i++){
    String employeeId = UUID.randomUUID().toString();
    employeeStmt.setString(1,employeeId);
    employeeStmt.setString(2,EMPLOYEES[i]);
    employeeStmt.setString(3,DESIGNATIONS[i]);
    employeeStmt.addBatch();
}
employeeStmt.executeBatch();

В показанном выше примере мы вставляем записи в таблицуEMPLOYEE, используяPreparedStatement.. Мы можем видеть, как значения, которые должны быть вставлены, устанавливаются в запросе, а затем добавляются в пакет для выполнения.

4. Заключение

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

Как всегда, код, относящийся к этой статье, можно найтиover on Github.