Асинхронный запуск нескольких запросов Sql в Vertx (Vert.x 3)

Я использую vertx-mysql-postgresql-client-3.3.0 и vertx-sql-common-3.3.0 Сначала я думал об использовании пакетной операции для вставки нескольких операторов, но выглядит так (http://vertx.io/docs/vertx-sql-common/java/#_batch_operations) не реализован в клиенте vertx-mysql-postgres.

Код, который обрабатывает данные публикации в db:

SQLConnection sqlConnection;
 List <JsonArray> targetParams = new ArrayList();
 for (String key : targetObject.getTargets().keySet()) {
    targetParams.add(new JsonArray().add(key).add(targetObject.getTargets().get(key)).add(targetObject.getId()));
 }
 int[] i = {targetObject.getTargets().size()};
 while(i[0]>=0) {
   sqlConnection.updateWithParams("INSERT INTO Targets (name,  id,language) VALUES (?,?,?)", taglineParams.get(i[0] - 1), result ->
{           
  if (result.succeeded()) {
      i[0]--;
 }

else { badRequest(context, "Error inserting error code: " +   result.cause().toString());
   }
 }); 
}

Код обработчика AsyncResult:

Handler<AsyncResult<SQLConnection>> sqlConnectionHandler = new Handler<AsyncResult<SQLConnection>>() {
    @Override
    public void handle(AsyncResult<SQLConnection> res) {
        if (res.succeeded()) {
            sqlConnection = res.result();
        } else {
            logger.error("Unable to create SQL connection: " + res.cause().toString());
        }
    }
};

Этот не работает и выдает ошибку Thread Blocked после первой вставки.

Любая идея, как я могу заставить работать несколько вставок?


person Community    schedule 10.07.2016    source источник


Ответы (3)


Vert.x — это асинхронная структура, однако код использует синхронную конструкцию, которая не будет работать. Существует цикл while, пока переменная не станет больше 0. но обновление управляющей переменной обновляется в асинхронном обработчике, что означает, что он не будет вызываться внутри цикла.

Зная это, цикл будет работать «вечно», пока планировщик потоков JVM не остановит его для запуска другого потока (который в конечном итоге обновит управляющую переменную). Теперь, когда планировщик остановил поток, Vert.x также уведомит вас о том, что вы заблокировали цикл событий, что означает, что вам следует пересмотреть свой код.

Я бы предложил либо объединить оператор SQL в большой оператор sql и выполнить его сразу, либо использовать цикл for. Обратите внимание, что цикл for также не на 100% безопасен. Скажем, вы вставляете 1 млн строк, вы также можете легко использовать более 2 секунд процессорного времени, и вы снова получите предупреждение.

Хорошим решением будет асинхронный цикл или, например, RX.

person Paulo Lopes    schedule 11.07.2016
comment
Используя цикл for, я также получаю тот же поток, который уже работает. Будет ли работать такой запрос, как INSERT INTO Targets (name, id,language) VALUES (?,?,?),(?,?,?);", taglineParams, result -> ? - person ; 11.07.2016

Я настоятельно рекомендую использовать CountDownLatch в таких ситуациях:

CountDownLatch latch = new CountDownLatch(targetObject.getTargets().size());
for (JsonArray params : targetParams) {
    sqlConnection.updateWithParams("INSERT INTO Targets (name,  id,language) VALUES (?,?,?)", params, result ->
    {
        if (!result.succeeded()) {
            badRequest(context, "Error inserting error code: " +   result.cause().toString());
        }
        latch.countDown();
    });
}

latch.await(3, TimeUnit.SECONDS);

Это все еще плохо для Vert.x, так как он будет блокировать поток, поэтому вам также следует подумать об изменении своей логики, а не ждать завершения процесса вообще.

person Alexey Soshin    schedule 12.07.2016

Я видел офисный API, пакетную операцию, возможно, вы можете использовать это.

List<JsonArray> batch = new ArrayList<>();
batch.add(new JsonArray().add("joe"));
batch.add(new JsonArray().add("jane"));

connection.batchWithParams("INSERT INTO emp (name) VALUES (?)", batch, res -> {
  if (res.succeeded()) {
    List<Integer> result = res.result();
  } else {
    // Failed!
  }
});
person zhenhui.wang    schedule 22.01.2017
comment
Вы тестировали это. Когда я проверил код, он говорит, что операция не поддерживается, потому что она не реализована. - person Tharanga; 29.11.2017