2016-07-10 2 views
1

Я использую 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-client.Выполнять несколько запросов Sql асинхронно в Vertx (Vert.x 3)

код, который обрабатывает почтовые данные в БД:

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 заблокированное ошибку после вставки первого.

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

ответ

0

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

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

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

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

+0

Использование для цикла также я получаю тот же самый поток, который уже работает. Будет ли запрос, такой как «INSERT INTO Targets» (имя, идентификатор, язык), VALUES (?,?,?), (?,?,?); », TaglineParams, result ->' work? – dreamhigh

0

я настоятельно рекомендую использовать 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, так как он будет блокировать поток, так что вы должны также рассмотреть вопрос об изменении вашей логики, а не ждать, процесс для завершения вообще.

0

Я видел офис API, batch operation, может быть, вы можете это использовать.

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! 
    } 
}); 
+0

Вы протестировали это. Я проверил код, который говорит, что операция не поддерживается, потому что она не реализована. – Tharanga