在Vert.x中使用SQL - Alexey Soshin


Vert.x是异步的。在Vert.x中执行数据库查询时,您显然正在传递回调。那么,它是异步的?:

conn.updateWithParams("insert into user (email, name, password) values (?, ?, ?)", params,
  (r) -> {
        if (r.succeeded()) {
            System.out.println(
"Ok!");
        }
        else {
            if (r.cause() instanceof MySQLException) {
                MySQLException cause = (MySQLException) r.cause();
                if (cause.errorMessage().errorCode() == 1062) {
                   
// Duplicate key, ignore
                }
            }

不完全对,看看queryWithParams 方法内部:

public SQLConnection queryWithParams(String sql, 
                                     JsonArray params, 
                                     Handler<AsyncResult<ResultSet>> resultHandler) {
    new JDBCQuery(vertx, 
        helper, 
        options, 
        ctx, 
        sql, 
        params).execute(conn, 
            statementsQueue, 
            resultHandler);
    return this;
}

JDBCQuery 是一个简单对象,有趣部分是execute()方法,进入AbstractJDBCAction看看这个方法:

public void execute(Connection conn, 
                    TaskQueue statementsQueue, 
                    Handler<AsyncResult<T>> resultHandler) {
  ctx.executeBlocking(future -> handle(conn, future), 
                      statementsQueue, resultHandler);
}

注意到调用的executeBlocking方法名称,你可能疑惑ctx来自哪里,其实来自JDBCClientImpl:

public SQLClient getConnection(Handler<AsyncResult<SQLConnection>> handler) {
  Context ctx = vertx.getOrCreateContext();
  getConnection(ctx, ar -> ctx.runOnContext(v -> handler.handle(ar)));
  return this;
}

结论是,最后,常规的Vert.x JDBC客户端没有任何魔力。它使用了一个简单的数据源:默认情况下为C3P0,但如果您愿意,也可以使用Hikari。您可能希望将池大小设置得更大,默认为15个连接
这种实现的主要目标很简单 - 不阻止事件循环(从不阻止事件循环)。对大多数用例来说,它实际上非常好。只是不要指望它会用JDBC做一些神奇的事情,就像让它无阻塞一样。