Vertx DataAccess 数据库访问
Posted Johnny屋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vertx DataAccess 数据库访问相关的知识,希望对你有一定的参考价值。
Vertx DataAccess 数据库访问
本篇主要来说一下 如何使用Vertx 来访问数据库 ,并且来提供 JDBC Client 和 Reactive mysql Client 访问Mysql的 两个 demo案例
先来看看官网 关于Vertx Data Access 都支持哪些,直接上图
可以看到 Vertx 支持很多数据访问 包括 Mysql 以及 Redis 和 MongoDB 等等
下面我分别来演示 JDBC client 和 Reactive MySQL client 这两种方式访问Mysql ,而MySQL client 已经被 deprecated 这里就不做演示了
1.JDBC client 访问Mysql
使用JDBC client 方式 去访问MySQL , 默认使用C3P0 数据库连接池
1.1 引入依赖
引入 vertx-jdbc-client 依赖访问数据库
// https://mvnrepository.com/artifact/io.vertx/vertx-jdbc-client
compile group: 'io.vertx', name: 'vertx-jdbc-client', version: '3.9.3'
//vertx 核心
compile 'io.vertx:vertx-core:3.9.3'
//添加 vertx-web组件 来进行 web 开发 提供一些如 路由等
compile 'io.vertx:vertx-web:3.9.3'
1.2 编写使用JDBC Client 访问数据库代码
1.直接使用 硬编码的方式配置 数据库信息,后面给优化成从外部访问
访问/person/list 接口去数据库查询 person表 并且返回 (这里面涉及 路由相关知识 可以看我上一篇
[Vertx-Web 路由] https://www.askajohnny.com/#/blog/179 Vertx-Web 路由
)
dbConfig 就是数据库相关配置
创建数据库访问客户端 通过 是不是很简单!!
SQLClient client = JDBCClient.createShared(vertx, dbConfig);
/**
* @author johnny
**/
public class ConfigMysqlNoFutureDemo extends AbstractVerticle {
private static Logger logger = LoggerFactory.getLogger(ConfigMysqlNoFutureDemo.class);
@Override
public void start() throws Exception {
Router router = Router.router(vertx);
//访问 person/list 接口 查询数据库
router.get("/person/list")
.handler(rc -> {
HttpServerResponse response = rc.response();
//1.使用 硬编码配置 数据库相关配置
JsonObject dbConfig = new JsonObject();
dbConfig.put("url", "jdbc:mysql://localhost:3306/vertx-demo");
dbConfig.put("driver_class", "com.mysql.cj.jdbc.Driver");
dbConfig.put("user", "root");
dbConfig.put("password", "root");
//创建 jdbcClient 连接
SQLClient client = JDBCClient.createShared(vertx, dbConfig);
//使用 数据库连接 去执行 sql
client.query("SELECT * FROM person", call -> {
if (call.succeeded()) {
logger.info("【select success】");
List<Person> list = new ArrayList<>();
ResultSet result = call.result();
result.getRows()
.forEach(jsonObject -> {
list.add(convertToPerson(jsonObject));
});
//返回结果
response.putHeader("Content-Type", "application/json");
response.putHeader("ChartSet", "utf-8");
response.end(GsonUtils.gson().toJson(list));
} else {
logger.error("【select fail {0} 】", call.cause());
}
});
});
vertx.createHttpServer()
.requestHandler(router)
.listen(7766);
}
private Person convertToPerson(JsonObject jsonObject) {
Long id = jsonObject.getLong("id");
String name = jsonObject.getString("name");
Integer age = jsonObject.getInteger("age");
Person person = new Person();
person.setId(id);
person.setName(name);
person.setAge(age);
return person;
}
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new ConfigMysqlNoFutureDemo());
}
}
访问 http://localhost:7766/person/list 可以看到 返回了 json 串
上面很简单 就是 SQLClient client = JDBCClient.createShared(vertx, dbConfig); 去获取一个访问数据的的连接
2. Reactive MySQL client
这是 Vertx 官方推荐的 做了一定优化的 访问Mysql 的 客户端,正常就使用这个访问Mysql 上面的案例只是 做一个比较 推荐这种方式
2.1 引入依赖
引入 vertx-mysql-client
省略core 和 web了
// https://mvnrepository.com/artifact/io.vertx/vertx-mysql-client
compile group: 'io.vertx', name: 'vertx-mysql-client', version: '3.9.3'
2.2 官方使用教程
贴一段 官方案例教程
MySQLConnectOptions connectOptions = new MySQLConnectOptions()
.setPort(3306)
.setHost("the-host")
.setDatabase("the-db")
.setUser("user")
.setPassword("secret");
// Pool options
PoolOptions poolOptions = new PoolOptions()
.setMaxSize(5);
// Create the client pool
MySQLPool client = MySQLPool.pool(connectOptions, poolOptions);
// A simple query
client
.query("SELECT * FROM users WHERE id='julien'")
.execute(ar -> {
if (ar.succeeded()) {
RowSet<Row> result = ar.result();
System.out.println("Got " + result.size() + " rows ");
} else {
System.out.println("Failure: " + ar.cause().getMessage());
}
// Now close the pool
client.close();
});
2.3 自定义MysqlUtils
对照着官方案例教程 我们来做一些工具类,这里还是 使用 硬编码 ,后续可以优化
/**
* @author johnny
* @create 2020-10-14 上午9:50
**/
public class MysqlUtils {
private static final MySQLConnectOptions CONNECT_OPTIONS = new MySQLConnectOptions();
private static final PoolOptions POOL_OPTIONS = new PoolOptions();
static {
CONNECT_OPTIONS
.setPort(3306)
.setHost("127.0.0.1")
.setDatabase("vertx-demo")
.setUser("root")
.setPassword("root");
// Pool options
POOL_OPTIONS.setMaxSize(5);
}
public static MySQLPool getMysqlPool(Vertx vertx) {
return MySQLPool.pool(vertx, CONNECT_OPTIONS, POOL_OPTIONS);
}
}
2.4 编写使用Reactive MySQL client 访问数据库代码
结合前面一篇的路由 ,这里提供实现一个 post接口 提交json 参数 然后保存到 数据库,紧接着获取最新的 自增ID 根据,自增Id 再查询出来数据,返回给客户端的需求
通过 MySQLPool pool = MysqlUtils.getMysqlPool(vertx);获取mysql连接池
MysqlUtils 上面自己封装的
使用 preparedQuery 可以提交带参数的查询语句 根据 ?使用Tuple.of 去填充查询参数
通过使用 rows.property(MySQLClient.LAST_INSERTED_ID);
来获取到 最新插入ID 很实用!!!
/**
* 使用 官方的 vertx-mysql-client 去访问 mysql
*
* @author johnny
* @create 2020-10-14 上午9:44
**/
public class VertxMysqlAccessDemo extends AbstractVerticle {
@Override
public void start() throws Exception {
Router router = Router.router(vertx);
Router personRouter = Router.router(vertx);
//save + query
personRouter.post("/save")
.handler(BodyHandler.create()) //一定要加,因为从body中获取json 需要这个handler
.handler(requestHandler -> {
HttpServerResponse response = requestHandler.response();
//从body中获取 前端传来的json串
JsonObject bodyAsJson = requestHandler.getBodyAsJson();
String name = bodyAsJson.getString("name");
int age = bodyAsJson.getInteger("age");
MySQLPool pool = MysqlUtils.getMysqlPool(vertx);
pool.preparedQuery("INSERT INTO person (name, age) VALUES (?, ?)")
.execute(Tuple.of(name, age), ar -> {
if (ar.succeeded()) {
RowSet<Row> rows = ar.result();
//获取到最新插入ID
long lastInsertId = rows.property(MySQLClient.LAST_INSERTED_ID);
System.out.println("lastInsert Id : " + lastInsertId);
//再查询出来
pool.preparedQuery("SELECT * FROM person where id = ?")
.execute(Tuple.of(lastInsertId), ar2 -> {
if (ar2.succeeded()) {
RowSet<Row> result = ar2.result();
Row row = result.iterator().next();
Person person = new Person();
person.setId(lastInsertId);
person.setName(row.getString("name"));
person.setAge(row.getInteger("age"));
response.putHeader("Content-Type", "application/json");
response.putHeader("Charset", "UTF-8");
response.end( JsonObject.mapFrom(person).toString());
}
});
} else {
System.out.println("Failure: " + ar.cause().getMessage());
}
});
});
//挂载二级路由
router.mountSubRouter("/person", personRouter);
vertx.createHttpServer()
.requestHandler(router)
.listen(8899);
}
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new VertxMysqlAccessDemo());
}
}
访问 http://localhost:8899/person/save 方法 (注意有二级路由挂载
)提交一个 json {"name":"vertx","age":99}
核心就是 去创建 Mysql连接池 提供连接Options配置 和 数据库连接池的 Options配置
MySQLPool.pool(vertx, CONNECT_OPTIONS, POOL_OPTIONS);
总结
本篇主要讲解了 2种方式 访问Mysql 数据库,一种是通过JDBC Client 另一种是通过 Reactive MySQL client 访问Mysql 数据库,并且都提供了 案例代码 。
存在的问题
1.数据库相关配置等 都是通过硬编码的 ,正式项目肯定不符合,后面我会写一篇关于 Vertx Config的文章教大家如何加载外部配置
2.可以看到第二个需求 先save 再query,本身只是2个数据库操作 但是回调域已经足够大了像是陷入了地狱一般,这就需要Vertx 的优雅的异步编程方式 Future+Promise 方式去解决啦,后面再写吧
以上是关于Vertx DataAccess 数据库访问的主要内容,如果未能解决你的问题,请参考以下文章
Software--Architecture--Design DataAccess 数据访问
C#连接Oracle的时候,Oracle.DataAccess.dll能连接数据库,Oracle.ManagedDataAccess却不能?