2016-07-10 10 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()); 
     } 
    } 
}; 

この1つは仕事と最初に挿入した後、スレッドブロックされたエラーを与えていません。

どのように複数の挿入を動作させることができますか?

答えて

0

Vert.xは非同期フレームワークですが、コードは動作しない同期構造を使用しています。変数が0より大きくなるまでwhileループがありますが、制御変数への更新は非同期ハンドラで更新されます。つまり、ループ内で呼び出されません。

これを知っていると、JVMスレッドスケジューラが他のスレッドを実行するまでループが "永遠"に実行されます(最終的には制御varを更新します)。スケジューラがスレッドを停止したので、イベントループをブロックしたVert.xによって通知されます。つまり、コードを修正する必要があります。

大きなSQL文でSQL文を連結してすぐに実行するか、forループを使用することをお勧めします。 forループも100%安全ではないことに注意してください。 1M行を挿入しているとすれば、2秒以上のCPU時間を簡単に使用することができ、警告が再び表示されます。

良い解決策は、例えば非同期ループであるか、RXのように見えます。

+0

forループを使用すると、同じスレッドですでに問題が発生しています。 "INSERT INTO Targets(name、id、language)VALUES(?、?、?);(?、?、?);"、taglineParams、result - > ' のようなクエリは役に立ちますか? – 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

関連する問題