[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-jdbc-kak-vypolnyat-batch-operatsii-v-jdbc":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":18,"progress":19,"seo":20},1180,"kak-vypolnyat-batch-operatsii-v-jdbc",36,"jdbc","JDBC","🔌","Как выполнять batch-операции в JDBC","Batch-операции (пакетные операции) — это механизм отправки нескольких SQL-команд на сервер за один сетевой вызов, значительно сокращающий количество обращений к СУБД и повышающий производительность.\n\nВместо отправки каждого SQL-запроса отдельно, batch-операции группируют запросы и отправляют их одним пакетом:\n\n- `addBatch()` — добавляет SQL-команду в пакет\n- `executeBatch()` — отправляет все накопленные команды на сервер\n- `clearBatch()` — очищает накопленный пакет\n\n### Сравнение производительности (вставка 10 000 записей)\n\n| Подход | Время | Сетевых обращений |\n|:-------|:------|:-----------------|\n| Одиночный INSERT | ~10 000 мс | 10 000 |\n| Batch (размер 1 000) | ~500 мс | 10 |\n| Batch + rewriteBatchedStatements | ~200 мс | 10 |\n\n\u003Cdetails>\n\u003Csummary>Batch с Statement\u003C\u002Fsummary>\n\n```java\npublic void batchWithStatement(Connection connection) throws SQLException {\n    try (Statement stmt = connection.createStatement()) {\n        connection.setAutoCommit(false);\n\n        stmt.addBatch(\"INSERT INTO products (name, price) VALUES ('Телефон', 29999)\");\n        stmt.addBatch(\"INSERT INTO products (name, price) VALUES ('Ноутбук', 74999)\");\n        stmt.addBatch(\"INSERT INTO products (name, price) VALUES ('Планшет', 19999)\");\n        stmt.addBatch(\"UPDATE products SET price = price * 0.9 WHERE price > 50000\");\n\n        int[] results = stmt.executeBatch();\n        connection.commit();\n\n        for (int i = 0; i \u003C results.length; i++) {\n            System.out.println(\"Команда \" + i + \": затронуто строк = \" + results[i]);\n        }\n    } catch (BatchUpdateException e) {\n        connection.rollback();\n        int[] updateCounts = e.getUpdateCounts();\n        for (int i = 0; i \u003C updateCounts.length; i++) {\n            if (updateCounts[i] == Statement.EXECUTE_FAILED) {\n                System.err.println(\"Команда \" + i + \" завершилась с ошибкой\");\n            }\n        }\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Batch с PreparedStatement (рекомендуемый подход)\u003C\u002Fsummary>\n\n```java\npublic void batchInsertUsers(Connection connection, List\u003CUser> users)\n        throws SQLException {\n    String sql = \"INSERT INTO users (name, email, age) VALUES (?, ?, ?)\";\n\n    try (PreparedStatement ps = connection.prepareStatement(sql)) {\n        connection.setAutoCommit(false);\n        int batchSize = 1000;\n        int count = 0;\n\n        for (User user : users) {\n            ps.setString(1, user.getName());\n            ps.setString(2, user.getEmail());\n            ps.setInt(3, user.getAge());\n            ps.addBatch();\n            count++;\n\n            \u002F\u002F Выполняем промежуточный batch каждые 1000 записей\n            if (count % batchSize == 0) {\n                ps.executeBatch();\n                ps.clearBatch();\n            }\n        }\n\n        \u002F\u002F Выполняем оставшиеся записи\n        ps.executeBatch();\n        connection.commit();\n    } catch (BatchUpdateException e) {\n        connection.rollback();\n        throw new RuntimeException(\"Ошибка batch-вставки\", e);\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Batch-операции с Spring JdbcTemplate\u003C\u002Fsummary>\n\n```java\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.jdbc.core.BatchPreparedStatementSetter;\n\npublic class UserRepository {\n\n    private final JdbcTemplate jdbcTemplate;\n\n    public UserRepository(JdbcTemplate jdbcTemplate) {\n        this.jdbcTemplate = jdbcTemplate;\n    }\n\n    public void batchInsert(List\u003CUser> users) {\n        String sql = \"INSERT INTO users (name, email, age) VALUES (?, ?, ?)\";\n\n        jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {\n            @Override\n            public void setValues(PreparedStatement ps, int i)\n                    throws SQLException {\n                User user = users.get(i);\n                ps.setString(1, user.getName());\n                ps.setString(2, user.getEmail());\n                ps.setInt(3, user.getAge());\n            }\n\n            @Override\n            public int getBatchSize() {\n                return users.size();\n            }\n        });\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\n### Важное\n\n- Batch-операции эффективны при вставке\u002Fобновлении от 100+ записей\n- Всегда оборачивайте batch в транзакцию (setAutoCommit(false) + commit())\n- Для больших объёмов разбивайте batch на части (обычно по 1000-5000 записей)\n- PreparedStatement batch безопаснее — защита от SQL Injection\n\n### Частые ошибки\n\n- Не отключать autoCommit — каждая команда коммитится отдельно, теряя смысл пакетирования\n- Накапливать слишком большой batch без промежуточного executeBatch() — может привести к OutOfMemoryError\n- Не обрабатывать BatchUpdateException — невозможно определить, какие записи вставлены успешно\n- Забывать clearBatch() после executeBatch() при обработке данных частями\n\n### Как используется в 2026\n\n- Spring Data JDBC поддерживает batch-вставки через saveAll() с настройкой spring.jdbc.template.batch-size\n- jOOQ предлагает типобезопасные batch-операции с автоматической оптимизацией\n- Для массовой загрузки всё чаще используется COPY (PostgreSQL) или LOAD DATA INFILE (MySQL)\n- В реактивном стеке R2DBC поддерживает batch через Statement.add()\n\n> **На собеседовании:** объясните зачем нужен batch (сокращение сетевых вызовов), назовите три метода (addBatch, executeBatch, clearBatch) и скажите про разбиение на части при большом объёме данных. Частый follow-up: что вернёт executeBatch() — массив int с количеством затронутых строк для каждой команды.","","middle",[15,16,17,7],"databases","performance","batch",[],null,{"title":21,"description":22,"ogTitle":21,"ogDescription":23,"keywords":24,"schemaAnswer":32,"featuredSnippetReady":33},"Batch-операции в JDBC -- Gymterview","Batch-операции JDBC: addBatch, executeBatch, clearBatch. Сравнение производительности, batch с PreparedStatement, Spring JdbcTemplate batchUpdate на собеседовании.","Пакетные операции в JDBC: сокращение сетевых вызовов, batch с PreparedStatement, разбиение на части.",[17,25,26,27,28,29,8,30,31],"addBatch","executeBatch","пакетные операции","BatchUpdateException","JdbcTemplate","Java","собеседование","Batch-операции отправляют несколько SQL-команд за один сетевой вызов. Методы: addBatch() добавляет команду, executeBatch() отправляет пакет, clearBatch() очищает. Вставка 10000 записей: одиночный INSERT ~10 сек, batch ~0.5 сек. Рекомендуется разбивать на части по 1000-5000 записей и оборачивать в транзакцию.",true]