java - How to merge database query results using Vertx SQL interface -
i use vertx common sql interface query table t1
, t2
, t3
in database tdb
, table s1
, s2
, s3
database sdb
, return them jsonobject
. final result should this
{ "t1": [{...},{...},...], "t2": [{...},{...},...], "t3": [{...},{...},...], "s1": [{...},{...},...], "s2": [{...},{...},...], "s3": [{...},{...},...] }
if 1 table, this
jdbcclient tdbclient = jdbcclient.createshared(vertx, tdbconfig, "tdb"); jdbcclient sdbclient = jdbcclient.createshared(vertx, sdbconfig, "sdb"); vertx.eventbus().consumer("myservice.getdata").handler(msg -> { tdbclient.getconnection(tconresult -> { if (tconresult.succeeded()) { sqlconnection tconnection = tconresult.result(); tconnection.query("select * t1", t1 -> { if (t1.succeeded()) { jsonarray t1result = new jsonarray(t1.result().getrows()); jsonobject allresult = new jsonobject() .put("t1", t1result); msg.reply(allresult); } else { msg.fail(1, "failt query t1"); } }); } else { msg.fail(1, "connot connection tdb"); } }); });
but since have many tables, find ugly way this
vertx.eventbus().consumer("myservice.getdata").handler(msg -> { tdbclient.getconnection(tconresult -> { if (tconresult.succeeded()) { sdbclient.getconnection(sconresult -> { if (sconresult.succeeded()) { sqlconnection tconnection = tconresult.result(); sqlconnection sconnection = sconresult.result(); tconnection.query("select * t1", t1 -> { if (t1.succeeded()) { tconnection.query("select * t2", t2 -> { if (t2.succeeded()) { tconnection.query("select * t3", t3 -> { if (t3.succeeded()) { sconnection.query("select * s1", s1 -> { if (s1.succeeded()) { sconnection.query("select * s2", s2 -> { if (s2.succeeded()) { sconnection.query("select * s3", s3 -> { if (s3.succeeded()) { jsonarray t1result = new jsonarray(t1.result().getrows()); jsonarray t2result = new jsonarray(t2.result().getrows()); jsonarray t3result = new jsonarray(t3.result().getrows()); jsonarray s1result = new jsonarray(s1.result().getrows()); jsonarray s2result = new jsonarray(s2.result().getrows()); jsonarray s3result = new jsonarray(s3.result().getrows()); jsonobject allresult = new jsonobject() .put("t1", t1result) .put("t2", t2result) .put("t3", t3result) .put("s1", s1result) .put("s2", s2result) .put("s3", s3result); msg.reply(allresult); } else {msg.fail(1, "failt query s3");}}); } else {msg.fail(1, "failt query s2");}}); } else {msg.fail(1, "failt query s1");}}); } else {msg.fail(1, "failt query t3");}}); } else {msg.fail(1, "failt query t2");}}); } else {msg.fail(1, "failt query t1");}}); } else {msg.fail(1, "connot connection sdb");}}); } else {msg.fail(1, "connot connection tdb");}}); });
but think i'm doing wrong, despite of ugly code, takes lot of time process because doesn't queries in parallel.
please suggest better way achieve this.
what experiencing here callback hell. vert.x provides features handle asyncresult
in more composable , convient way callbacks. called future
. suggest read them in documentation. future
placeholder results of asynchronous calls. vert.x full of asynchronous calls. if asynchronous calls depend on each other typically end callback hell. future
can this:
future<sqlconnection> tconresultfuture = future.future(); tdbclient.getconnection(tconresult -> { if (tconresult.succeeded()) { logger.info("yeah got connection! tcon"); tconresultfuture.complete(tconresult.result()); } else { tconresultfuture.fail(tconresult.cause()); } });
the handler
asyncresult<sqlconnection>
put asynchronous result of getting sqlconnection
future tconresultfuture
. can handler
future
, wait asynchronous result getconnection
:
tconresultfuture.sethandler(result -> { // ... });
but wouldn't make sense first handler
. think of example yours – many depending futures
. use example add second connection – sconresult
:
future<sqlconnection> sconresultfuture = future.future(); sdbclient.getconnection(sconresult -> { if (sconresult.succeeded()) { logger.info("yeah got connection! scon"); sconresultfuture.complete(sconresult.result()); } else { sconresultfuture.fail(sconresult.cause()); } });
so lets say, want wait both future
results because depend on each other. here use vert.x' compositefuture
:
compositefuture.all(tconresultfuture, sconresultfuture).sethandler(connections -> { if (connections.succeeded()) { logger.info("both connections ready use!"); sqlconnection tcon = tconresultfuture.result(); sqlconnection scon = sconresultfuture.result(); // stuff... } else { logger.severe("both or 1 connections attempt failed!"); } });
the compositefuture
waits future tconresultfuture
, future sconresultfuture
complete or not , call handler
. both asynchronous results finished , can call results.
you , nice thing, both asynchronous calls done concurrently.
Comments
Post a Comment