2.5.1、数据库初始化
维基数据库模式由一个单独的Pages表组成,其中包含以下列:
列 | 类型 | 描述 |
---|---|---|
Id | Integer | 主键 |
Name | Charactors | 维基页面的名称, 必须是独一无二的 |
Content | Text | 维基页面的Markdown文本 |
数据库操作将是典型的创建,读取,更新,删除操作。为简单起见,我们将相应的SQL查询作为MainVerticle类的静态字段存储。 请注意,它们是用HSQLDB能理解的SQL方言编写的, 但是其他关系数据库可能不一定支持:
private static final String SQL_CREATE_PAGES_TABLE = "create table if not exists Pages (Id integer identity primary key, Name varchar(255) unique, Content clob)";
private static final String SQL_GET_PAGE = "select Id, Content from Pages where Name = ?"; (1)
private static final String SQL_CREATE_PAGE = "insert into Pages values (NULL, ?, ?)";
private static final String SQL_SAVE_PAGE = "update Pages set Content = ? where Id = ?";
private static final String SQL_ALL_PAGES = "select Name from Pages";
private static final String SQL_DELETE_PAGE = "delete from Pages where Id = ?";
查询中的?号是占位符,用于在执行查询时传递数据,且可让Vert.x JDBC客户端防止SQL注入。
应用的Verticle需要持有作为数据库连接的JDBCClient对象(来自io.vertx.ext.jdbc包)的引用。我们使用MainVerticle中的一个字段存储这个引用,我们也使用来自org.slf4j包包的类创建一个通用日志记录器:
private JDBCClient dbClient;
private static final Logger LOGGER = LoggerFactory.getLogger(MainVerticle.class);
以下是prepareDatabase方法的完整实现。 它尝试获取一个JDBC客户端连接, 然后如果Pages表不存在,则执行SQL查询以创建Pages表:
private Future<Void> prepareDatabase() {
Future<Void> future = Future.future();
dbClient = JDBCClient.createShared(vertx, new JsonObject() (1)
.put("url", "jdbc:hsqldb:file:db/wiki") (2)
.put("driver_class", "org.hsqldb.jdbcDriver") (3)
.put("max_pool_size", 30)); (4)
dbClient.getConnection(ar -> { (5)
if (ar.failed()) {
LOGGER.error("Could not open a database connection", ar.cause());
future.fail(ar.cause()); (6)
} else {
SQLConnection connection = ar.result(); (7)
connection.execute(SQL_CREATE_PAGES_TABLE, create -> {
connection.close(); (8)
if (create.failed()) {
LOGGER.error("Database preparation error", create.cause());
future.fail(create.cause());
} else {
future.complete(); (9)
}
});
}
});
return future;
}
createShared创建一个共享连接,以便在vertx已知的Verticles之间共享,一般来说,这是一件好事;
JDBC客户端连接是通过传递一个Vert.x JSON对象来实现的。这里的url是JDBC URL;
就像url一样,driver_class是特定于正在使用的JDBC驱动程序,指向驱动程序类;
max_pool_size是并发连接数。我们在这里选择了30,但只是一个任意数;
获取连接是一个异步操作,给我们一个AsyncResult <SQLConnection>。然后必须进行测试以查看是否可以建立连接(实际上AsyncResult是Future的超级接口);
如果无法获取SQL连接,则Future的方法将会失败,失败的内容是通过cause方法提供的AsyncResult提供的异常;
SQLConnection是AsyncResult成功的结果。我们可以使用它来执行SQL查询;
在检查SQL查询是否成功之前,我们必须通过调用close来释放它,否则JDBC客户端连接池最终可能会耗尽;
成功完成Future的方法。
Vert.x项目支持的SQL数据库模块目前不提供超出传递SQL查询(例如,对象关系映射器)的任何内容,因为它们专注于提供对数据库的异步访问。 然而,没有什么禁止使用来自社区的更先进的模块,我们特别建议检查社区其它的项目,如这个jooq的Vert.x生成器或POJO映射器。