두 번째 방법은 좀 더 효율적이지만 훨씬 더 좋은 방법은 일괄 적으로 실행하는 것입니다.
public void executeBatch(List<Entity> entities) throws SQLException {
try (
Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(SQL);
) {
for (Entity entity : entities) {
statement.setObject(1, entity.getSomeProperty());
// ...
statement.addBatch();
}
statement.executeBatch();
}
}
그러나 한 번에 실행할 수있는 배치 수는 JDBC 드라이버 구현에 따라 다릅니다. 예를 들어 1000 배치마다 실행할 수 있습니다.
public void executeBatch(List<Entity> entities) throws SQLException {
try (
Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(SQL);
) {
int i = 0;
for (Entity entity : entities) {
statement.setObject(1, entity.getSomeProperty());
// ...
statement.addBatch();
i++;
if (i % 1000 == 0 || i == entities.size()) {
statement.executeBatch(); // Execute every 1000 items.
}
}
}
}
멀티 스레드 환경의 경우 다음과 같이 try-with-resources 문을 사용하여 일반 JDBC 관용구에 따라 동일한 메서드 블록 내에서 가능한 가장 짧은 범위의 연결 및 문을 획득하고 닫으면 이에 대해 걱정할 필요가 없습니다 . 스 니펫 위.
이러한 일괄 처리가 트랜잭션 인 경우 연결 자동 커밋을 해제하고 모든 일괄 처리가 완료 될 때만 트랜잭션을 커밋하려고합니다. 그렇지 않으면 첫 번째 일괄 처리가 성공할 때 데이터베이스가 더티 데이터베이스가 될 수 있습니다.
public void executeBatch(List<Entity> entities) throws SQLException {
try (Connection connection = dataSource.getConnection()) {
connection.setAutoCommit(false);
try (PreparedStatement statement = connection.prepareStatement(SQL)) {
// ...
try {
connection.commit();
} catch (SQLException e) {
connection.rollback();
throw e;
}
}
}
}
sql
는 루프에서 변경되지 않습니까? 해당 쿼리가 루프의 각 반복마다 변경되지 않는 경우 왜 새로운PreparedStatement
무엇입니까 (첫 번째 코드 스 니펫에서)? 그렇게하는 이유가 있습니까?