protected final void batchUpdate(@NonNull List batchupdate) { ArrayList sqls = new ArrayList<>(batchupdate); this.connection = connect(); if (sqls.size() == 0) return; if (!hasStartWriteToDb) try { hasStartWriteToDb = true; final Statement batchStatement = this.connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); final int processedCount = sqls.size(); // Prevent automatically sending db instructions this.connection.setAutoCommit(false); for (final String sql : sqls) batchStatement.addBatch(sql); if (processedCount > 10_000) CustomContainersMainClass.getInstance().sendLogMsg(Level.WARNING, "Updating your database (" + processedCount + " entries)... PLEASE BE PATIENT THIS WILL TAKE " + (processedCount > 50_000 ? "10-20 MINUTES" : "5-10 MINUTES") + " - If server will print a crash report, ignore it, update will proceed."); // Set the flag to start time notifications timer batchUpdateGoingOn = true; // Notify console that progress still is being made new Timer().scheduleAtFixedRate(new TimerTask() { @Override public void run() { if (batchUpdateGoingOn) CustomContainersMainClass.getInstance().sendLogMsg(Level.WARNING, "Still executing, DO NOT SHUTDOWN YOUR SERVER."); else cancel(); } }, 1000 * 30, 1000 * 30); // Execute batchStatement.executeBatch(); // This will block the thread this.connection.commit(); CustomContainersMainClass.getInstance().sendLogMsg(Level.INFO, "Updated " + processedCount + " database entries."); } catch (final Throwable t) { t.printStackTrace(); } finally { try { this.connection.setAutoCommit(true); this.connection.setAutoCommit(true); } catch (final SQLException ex) { ex.printStackTrace(); } hasStartWriteToDb = false; // Even in case of failure, cancel batchUpdateGoingOn = false; } }