A
A
Alex Fox2020-04-22 13:46:21
Java
Alex Fox, 2020-04-22 13:46:21

Is it correct to use CompletableFuture and JdbcTemplate in this way?

Hello. There is a task: to make one call to one database and another call to another database. Take action on the results.
My current implementation is as follows:
Dao1 makes a select query1.
Dao2 makes select query2.
We do processing of results of two requests.

It would be desirable request1 and request2 to do simultaneously. Implemented like this:

@Async
public CompletableFuture<Response1> query1(){
    return CompletableFuture.completedFuture(jdbcTemplate1.query(sql, , ))
}
@Async
public CompletableFuture<Response2> query2(){
    return CompletableFuture.completedFuture(jdbcTemplate2.query(sql, , ))
}


Further in the code:

CompletableFuture<Response1> response1Future = query1();
 CompletableFuture<Response2> response2Future = query2();

 CompletableFuture.allOf(response1Future, response2Future).join();
//

How good or bad is this approach? I would like to know the opinions of experienced people.!
Thanks.!

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sergey Shvyrev, 2020-04-23
@AlexFox2019

  1. Get rid of the CompletionStage interface instantiation . True reactionaries write their own interpretations.
  2. We abstract from the return value through an interface or an abstract class. For example , DBResponse . Tomorrow you will get tired of the muscle, go to the nose. It will be enough to rewrite the interface.
  3. We unify the data acquisition by bringing the same type variables into the method signature. queryAsync Change the DSL to jooq tomorrow - just one rewrite method will suffice.
  4. Try to get rid of JOIN. A very expensive method that roughly converts reactive programming to imperative programming. Use thenAcceptAsync, exceptionallyAsync, handleAsync result() method

public CompletionStage<DBResponse> query1(){
        return queryAsync(jdbc, sql, param1, param2, ... paramN);
    }

    public CompletionStage<DBResponse> query2(){
        return queryAsync(jdbc, sql, param2, param3, ... paramN);
    }

    public CompletionStage<DBResponse> queryAsync(JDBC jdbc, sql, Objects ... params){
        return CompletableFuture.supplyAsync(() -> {
            return jdbc.query(sql, params);
        }).thenApplyAsync(DBResponse::of);
    }

//    далее в коде

    void result(){
        CompletableFuture.allOf(query1(), query2())
                .thenAcceptAsync( ... );
    }

    public static interface DBResponse {
        default DBResponse of(Response resp){
            ...;
        }
    }

PS Didn't write anything about concurency , don't know how you use it. IMHO it is convenient to instantiate a separate pool for each type of operation (disk, http, sql, ui, ...).

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question