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 数据库访问的主要内容,如果未能解决你的问题,请参考以下文章

DataAccess通用数据库访问类,简单易用,功能强悍

Software--Architecture--Design DataAccess 数据访问

C#连接Oracle的时候,Oracle.DataAccess.dll能连接数据库,Oracle.ManagedDataAccess却不能?

vertx应用程序中的CORS问题不起作用

vertx HTTPS (SSL/TLS) 服务器不工作。我无法访问 https://localhost

Vertx 路由初体验