3.3.3、减少JDBC客户端样板代码
到目前为止,我们已经看到完成SQL查询的步骤:
- 获取连接;
- 执行请求;
- 释放连接。
这导致代码中每个异步操作都需要进行大量的错误处理, 如:
dbClient.getConnection(car -> {
if (car.succeeded()) {
SQLConnection connection = car.result();
connection.query(sqlQueries.get(SqlQuery.ALL_PAGES), res -> {
connection.close();
if (res.succeeded()) {
List<String> pages = res.result()
.getResults()
.stream()
.map(json -> json.getString(0))
.sorted()
.collect(Collectors.toList());
message.reply(new JsonObject().put("pages", new JsonArray(pages)));
} else {
reportQueryError(message, res.cause());
}
});
} else {
reportQueryError(message, car.cause());
}
});
从Vert.x 3.5.0开始,JDBC客户端现在支持一次性操作:获取连接->执行SQL操作->内部释放连接。 以上代码可简化为:
dbClient.query(sqlQueries.get(SqlQuery.ALL_PAGES), res -> {
if (res.succeeded()) {
List<String> pages = res.result()
.getResults()
.stream()
.map(json -> json.getString(0))
.sorted()
.collect(Collectors.toList());
message.reply(new JsonObject().put("pages", new JsonArray(pages)));
} else {
reportQueryError(message, res.cause());
}
});
这对于单个操作获取连接的情况非常有用。在性能方面,重用连接进行串联SQL操作更好。
该类的其余部分由当消息来临时由onMessage调用的私有方法组成:
private void fetchAllPages(Message<JsonObject> message) {
dbClient.query(sqlQueries.get(SqlQuery.ALL_PAGES), res -> {
if (res.succeeded()) {
List<String> pages = res.result()
.getResults()
.stream()
.map(json -> json.getString(0))
.sorted()
.collect(Collectors.toList());
message.reply(new JsonObject().put("pages", new JsonArray(pages)));
} else {
reportQueryError(message, res.cause());
}
});
}
private void fetchPage(Message<JsonObject> message) {
String requestedPage = message.body().getString("page");
JsonArray params = new JsonArray().add(requestedPage);
dbClient.queryWithParams(sqlQueries.get(SqlQuery.GET_PAGE), params, fetch -> {
if (fetch.succeeded()) {
JsonObject response = new JsonObject();
ResultSet resultSet = fetch.result();
if (resultSet.getNumRows() == 0) {
response.put("found", false);
} else {
response.put("found", true);
JsonArray row = resultSet.getResults().get(0);
response.put("id", row.getInteger(0));
response.put("rawContent", row.getString(1));
}
message.reply(response);
} else {
reportQueryError(message, fetch.cause());
}
});
}
private void createPage(Message<JsonObject> message) {
JsonObject request = message.body();
JsonArray data = new JsonArray()
.add(request.getString("title"))
.add(request.getString("markdown"));
dbClient.updateWithParams(sqlQueries.get(SqlQuery.CREATE_PAGE), data, res -> {
if (res.succeeded()) {
message.reply("ok");
} else {
reportQueryError(message, res.cause());
}
});
}
private void savePage(Message<JsonObject> message) {
JsonObject request = message.body();
JsonArray data = new JsonArray()
.add(request.getString("markdown"))
.add(request.getString("id"));
dbClient.updateWithParams(sqlQueries.get(SqlQuery.SAVE_PAGE), data, res -> {
if (res.succeeded()) {
message.reply("ok");
} else {
reportQueryError(message, res.cause());
}
});
}
private void deletePage(Message<JsonObject> message) {
JsonArray data = new JsonArray().add(message.body().getString("id"));
dbClient.updateWithParams(sqlQueries.get(SqlQuery.DELETE_PAGE), data, res -> {
if (res.succeeded()) {
message.reply("ok");
} else {
reportQueryError(message, res.cause());
}
});
}
private void reportQueryError(Message<JsonObject> message, Throwable cause) {
LOGGER.error("Database query error", cause);
message.fail(ErrorCodes.DB_ERROR.ordinal(), cause.getMessage());
}