• vertx-mysql-client/java/


    Reactive MySQL Client是MySQL的客户端,它具有直接的API,专注于可伸缩性和低开销。

    特征

    • 事件驱动

    • 轻巧的

    • 内置连接池

    • 准备查询缓存

    • 游标支持

    • 行流

    • RxJava 1和RxJava 2

    • 直接存储到对象,没有不必要的副本

    • Java 8日期和时间

    • 存储过程支持

    • TLS / SSL支持

    • MySQL实用程序命令支持

    • 使用MySQL和MariaDB

    • 丰富的排序规则和字符集支持

    用法

    要使用反应性MySQL客户端,请将以下依赖项添加到构建描述符的“ 依赖项”部分:

    • Maven(在您的中pom.xml):

    <dependency>
     <groupId>io.vertx</groupId>
     <artifactId>vertx-mysql-client</artifactId>
     <version>3.8.4</version>
    </dependency>
    • Gradle(在您的build.gradle文件中):

    dependencies {
     compile 'io.vertx:vertx-mysql-client:3.8.4'
    }

    入门

    这是连接,查询和断开连接的最简单方法

    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'", 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();
    });

    连接到MySQL

    大多数时候,您将使用池连接到MySQL:

    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 pooled client
    MySQLPool client = MySQLPool.pool(connectOptions, poolOptions);

    池化的客户端使用连接池,任何操作都将从池中借用连接以执行该操作并将其释放到池中。

    如果使用Vert.x运行,则可以将其传递给您的Vertx实例:

    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 pooled client
    MySQLPool client = MySQLPool.pool(vertx, connectOptions, poolOptions);

    当您不再需要池时,您需要释放它:

    pool.close();

    当您需要在同一连接上执行多个操作时,需要使用一个client connection

    您可以轻松地从游泳池中获得一个:

    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 pooled client
    MySQLPool client = MySQLPool.pool(vertx, connectOptions, poolOptions);
    
    // Get a connection from the pool
    client.getConnection(ar1 -> {
    
      if (ar1.succeeded()) {
    
        System.out.println("Connected");
    
        // Obtain our connection
        SqlConnection conn = ar1.result();
    
        // All operations execute on the same connection
        conn.query("SELECT * FROM users WHERE id='julien'", ar2 -> {
          if (ar2.succeeded()) {
            conn.query("SELECT * FROM users WHERE id='emad'", ar3 -> {
              // Release the connection to the pool
              conn.close();
            });
          } else {
            // Release the connection to the pool
            conn.close();
          }
        });
      } else {
        System.out.println("Could not connect: " + ar1.cause().getMessage());
      }
    });

    完成连接后,必须关闭它才能将其释放到池中,以便可以重用它。

    组态

    您可以通过多种方法来配置客户端。

    数据对象

    配置客户端的一种简单方法是指定MySQLConnectOptions数据对象。

    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 pool from the data object
    MySQLPool pool = MySQLPool.pool(vertx, connectOptions, poolOptions);
    
    pool.getConnection(ar -> {
      // Handling your connection
    });

    排序规则和字符集

    Reactive MySQL客户端支持配置排序规则或字符集,并将它们映射到相关的java.nio.charset.Charset例如,您可以为类似的连接指定字符集

    MySQLConnectOptions connectOptions = new MySQLConnectOptions();
    
    // set connection character set to utf8 instead of the default charset utf8mb4
    connectOptions.setCharset("utf8");

    您也可以为连接指定排序规则,例如

    MySQLConnectOptions connectOptions = new MySQLConnectOptions();
    
    // set connection collation to utf8_general_ci instead of the default collation utf8mb4_general_ci
    // setting a collation will override the charset option
    connectOptions.setCharset("gbk");
    connectOptions.setCollation("utf8_general_ci");

    MySQL将utf8mb4作为默认字符集。请注意,在数据对象上设置排序规则将覆盖charset选项。

    您可以执行SQL SHOW COLLATION;SHOW CHARACTER SET;获取受支持的排序规则和字符集。

    有关MySQL字符集和排序规则的更多信息,请参见《MySQL参考手册》

    连接属性

    您也可以使用setPropertiesaddProperty方法配置连接属性注意setProperties将覆盖默认的客户端属性。

    MySQLConnectOptions connectOptions = new MySQLConnectOptions();
    
    // Add a connection attribute
    connectOptions.addProperty("_java_version", "1.8.0_212");
    
    // Override the attributes
    Map<String, String> attributes = new HashMap<>();
    attributes.put("_client_name", "myapp");
    attributes.put("_client_version", "1.0.0");
    connectOptions.setProperties(attributes);

    有关客户端连接属性的更多信息,请参见《MySQL参考手册》

    useAffectedRows

    您可以配置useAffectedRows选项,以决定CLIENT_FOUND_ROWS在连接到服务器时是否设置标志。如果CLIENT_FOUND_ROWS指定标志,则受影响的行数是找到的而不是受影响的行的数值。

    有关更多信息,请参见《MySQL参考手册》。

    连接URI

    除了使用MySQLConnectOptions数据对象进行配置之外,当您要使用连接URI进行配置时,我们还为您提供了另一种连接方法:

    String connectionUri = "mysql://dbuser:secretpassword@database.server.com:3211/mydb";
    
    // Create the pool from the connection URI
    MySQLPool pool = MySQLPool.pool(connectionUri);
    
    // Create the connection from the connection URI
    MySQLConnection.connect(vertx, connectionUri, res -> {
      // Handling your connection
    });

    有关连接字符串格式的更多信息,请参见《MySQL参考手册》

    当前客户端在连接uri中支持以下参数关键字(关键字不区分大小写)

    • 主办

    • 港口

    • 用户

    • 密码

    • 图式

    • 插座

    • useAffectedRows

    运行查询

    当您不需要事务或运行单个查询时,可以直接在池上运行查询。池将使用其连接之一来运行查询并将结果返回给您。

    这是运行简单查询的方法:

    client.query("SELECT * FROM users WHERE id='julien'", ar -> {
      if (ar.succeeded()) {
        RowSet<Row> result = ar.result();
        System.out.println("Got " + result.size() + " rows ");
      } else {
        System.out.println("Failure: " + ar.cause().getMessage());
      }
    });

    准备好的查询

    您可以对准备好的查询执行相同的操作。

    SQL字符串可以使用数据库语法“?”按位置引用参数。

    client.preparedQuery("SELECT * FROM users WHERE id=?", Tuple.of("julien"), ar -> {
      if (ar.succeeded()) {
        RowSet<Row> rows = ar.result();
        System.out.println("Got " + rows.size() + " rows ");
      } else {
        System.out.println("Failure: " + ar.cause().getMessage());
      }
    });

    查询方法提供了一个RowSet适用于SELECT查询的异步实例

    client.preparedQuery("SELECT first_name, last_name FROM users", ar -> {
      if (ar.succeeded()) {
        RowSet<Row> rows = ar.result();
        for (Row row : rows) {
          System.out.println("User " + row.getString(0) + " " + row.getString(1));
        }
      } else {
        System.out.println("Failure: " + ar.cause().getMessage());
      }
    });

    UPDATE / INSERT查询:

    client.preparedQuery("INSERT INTO users (first_name, last_name) VALUES (?, ?)", Tuple.of("Julien", "Viet"), ar -> {
      if (ar.succeeded()) {
        RowSet<Row> rows = ar.result();
        System.out.println(rows.rowCount());
      } else {
        System.out.println("Failure: " + ar.cause().getMessage());
      }
    });

    Row让您按索引访问数据

    System.out.println("User " + row.getString(0) + " " + row.getString(1));

    或按名称

    System.out.println("User " + row.getString("first_name") + " " + row.getString("last_name"));

    客户端不会在这里做任何魔术,并且无论您的SQL文本如何,列名都将用表中的名称标识。

    您可以访问多种类型

    String firstName = row.getString("first_name");
    Boolean male = row.getBoolean("male");
    Integer age = row.getInteger("age");

    您可以缓存准备好的查询:

    connectOptions.setCachePreparedStatements(true);

    分批

    您可以执行准备好的批处理

    List<Tuple> batch = new ArrayList<>();
    batch.add(Tuple.of("julien", "Julien Viet"));
    batch.add(Tuple.of("emad", "Emad Alblueshi"));
    
    // Execute the prepared batch
    client.preparedBatch("INSERT INTO USERS (id, name) VALUES (?, ?)", batch, res -> {
      if (res.succeeded()) {
    
        // Process rows
        RowSet<Row> rows = res.result();
      } else {
        System.out.println("Batch failed " + res.cause());
      }
    });

    MySQL LAST_INSERT_ID

    如果在表中插入一条记录,则可以获得自动递增的值。

    client.query("INSERT INTO test(val) VALUES ('v1')", ar -> {
      if (ar.succeeded()) {
        RowSet<Row> rows = ar.result();
        int lastInsertId = rows.property(MySQLClient.LAST_INSERTED_ID);
        System.out.println("Last inserted id is: " + lastInsertId);
      } else {
        System.out.println("Failure: " + ar.cause().getMessage());
      }
    });

    有关更多信息,请参见如何获取最后插入行的唯一ID

    使用连接

    当需要执行顺序查询(不执行事务)时,可以创建一个新连接或从池中借用一个:

    pool.getConnection(ar1 -> {
      if (ar1.succeeded()) {
        SqlConnection connection = ar1.result();
    
        connection.query("SELECT * FROM users WHERE id='julien'", ar2 -> {
          if (ar1.succeeded()) {
            connection.query("SELECT * FROM users WHERE id='paulo'", ar3 -> {
              // Do something with rows and return the connection to the pool
              connection.close();
            });
          } else {
            // Return the connection to the pool
            connection.close();
          }
        });
      }
    });

    可以创建准备好的查询:

    connection.prepare("SELECT * FROM users WHERE first_name LIKE ?", ar1 -> {
      if (ar1.succeeded()) {
        PreparedQuery pq = ar1.result();
        pq.execute(Tuple.of("julien"), ar2 -> {
          if (ar2.succeeded()) {
            // All rows
            RowSet<Row> rows = ar2.result();
          }
        });
      }
    });
    注意
    准备好的查询缓存取决于,setCachePreparedStatements而不取决于您是创建准备好的查询还是使用direct prepared queries

    PreparedQuery 可以执行有效的批处理:

    connection.prepare("INSERT INTO USERS (id, name) VALUES (?, ?)", ar1 -> {
      if (ar1.succeeded()) {
        PreparedQuery prepared = ar1.result();
    
        // Create a query : bind parameters
        List<Tuple> batch = new ArrayList();
    
        // Add commands to the createBatch
        batch.add(Tuple.of("julien", "Julien Viet"));
        batch.add(Tuple.of("emad", "Emad Alblueshi"));
    
        prepared.batch(batch, res -> {
          if (res.succeeded()) {
    
            // Process rows
            RowSet<Row> rows = res.result();
          } else {
            System.out.println("Batch failed " + res.cause());
          }
        });
      }
    });

    使用交易

    连接交易

    您可以使用SQL BEGINCOMMIT执行事务ROLLBACK,如果这样做,则必须使用SqlConnection和自己进行管理。

    或者,您可以使用的交易API SqlConnection

    pool.getConnection(res -> {
      if (res.succeeded()) {
    
        // Transaction must use a connection
        SqlConnection conn = res.result();
    
        // Begin the transaction
        Transaction tx = conn.begin();
    
        // Various statements
        conn.query("INSERT INTO Users (first_name,last_name) VALUES ('Julien','Viet')", ar1 -> {
          if (ar1.succeeded()) {
            conn.query("INSERT INTO Users (first_name,last_name) VALUES ('Emad','Alblueshi')", ar2 -> {
              if (ar2.succeeded()) {
                // Commit the transaction
                tx.commit(ar3 -> {
                  if (ar3.succeeded()) {
                    System.out.println("Transaction succeeded");
                  } else {
                    System.out.println("Transaction failed " + ar3.cause().getMessage());
                  }
                  // Return the connection to the pool
                  conn.close();
                });
              } else {
                // Return the connection to the pool
                conn.close();
              }
            });
          } else {
            // Return the connection to the pool
            conn.close();
          }
        });
      }
    });

    当PostgreSQL报告当前事务失败时(例如,臭名昭著的当前事务被中止,命令被忽略直到事务块结束),事务被回滚并被abortHandler 调用:

    tx.abortHandler(v -> {
      System.out.println("Transaction failed => rollbacked");
    });

    简化的交易API

    使用池时,可以直接在池上启动事务。

    它从池中借用连接,开始事务,并在事务结束时释放与池的连接。

    pool.begin(res -> {
      if (res.succeeded()) {
    
        // Get the transaction
        Transaction tx = res.result();
    
        // Various statements
        tx.query("INSERT INTO Users (first_name,last_name) VALUES ('Julien','Viet')", ar1 -> {
          if (ar1.succeeded()) {
            tx.query("INSERT INTO Users (first_name,last_name) VALUES ('Emad','Alblueshi')", ar2 -> {
              if (ar2.succeeded()) {
                // Commit the transaction
                // the connection will automatically return to the pool
                tx.commit(ar3 -> {
                  if (ar3.succeeded()) {
                    System.out.println("Transaction succeeded");
                  } else {
                    System.out.println("Transaction failed " + ar3.cause().getMessage());
                  }
                });
              }
            });
          } else {
            // No need to close connection as transaction will abort and be returned to the pool
          }
        });
      }
    });
    注意
    此代码不会关闭连接,因为在事务处理时它将始终释放回池中

    游标和流

    默认情况下,准备好的查询执行会提取所有行,您可以使用 Cursor来控制要读取的行数:

    connection.prepare("SELECT * FROM users WHERE age > ?", ar1 -> {
      if (ar1.succeeded()) {
        PreparedQuery pq = ar1.result();
    
        // Create a cursor
        Cursor cursor = pq.cursor(Tuple.of(18));
    
        // Read 50 rows
        cursor.read(50, ar2 -> {
          if (ar2.succeeded()) {
            RowSet<Row> rows = ar2.result();
    
            // Check for more ?
            if (cursor.hasMore()) {
              // Repeat the process...
            } else {
              // No more rows - close the cursor
              cursor.close();
            }
          }
        });
      }
    });

    游标过早释放时应将其关闭:

    cursor.read(50, ar2 -> {
      if (ar2.succeeded()) {
        // Close the cursor
        cursor.close();
      }
    });

    还可以为游标提供流API,这会更加方便,特别是对于Rxified版本而言。

    connection.prepare("SELECT * FROM users WHERE age > ?", ar1 -> {
      if (ar1.succeeded()) {
        PreparedQuery pq = ar1.result();
    
        // Fetch 50 rows at a time
        RowStream<Row> stream = pq.createStream(50, Tuple.of(18));
    
        // Use the stream
        stream.exceptionHandler(err -> {
          System.out.println("Error: " + err.getMessage());
        });
        stream.endHandler(v -> {
          System.out.println("End of stream");
        });
        stream.handler(row -> {
          System.out.println("User: " + row.getString("last_name"));
        });
      }
    });

    流将批量读取行50并将其流化,将行传递到处理程序后,将50读取新一批,依此类推。

    可以恢复或暂停该流,已加载的行将保留在内存中,直到被传递为止,并且游标将停止迭代。

    MySQL类型映射

    当前客户端支持以下MySQL类型

    • BOOL,BOOLEAN(java.lang.Byte

    • 忍者(java.lang.Byte

    • SMALLINT(java.lang.Short

    • MEDIUMINT(java.lang.Integer

    • INT,INTEGER(java.lang.Integer

    • 币种(java.lang.Long

    • 浮标(java.lang.Float

    • 双(java.lang.Double

    • 数值(io.vertx.sqlclient.data.Numeric

    • 日期(java.time.LocalDate

    • DATETIME(java.time.LocalDateTime

    • 时间(java.time.Duration

    • 时间戳(java.time.LocalDateTime

    • 年(java.lang.Short

    • 字符(java.lang.String

    • VARCHAR(java.lang.String

    • 二进制(io.vertx.core.buffer.Buffer

    • VARBINARY(io.vertx.core.buffer.Buffer

    • 天黑宝(io.vertx.core.buffer.Buffer

    • TINYTEXT(java.lang.String

    • BLOB(io.vertx.core.buffer.Buffer

    • 文字(java.lang.String

    • 中号(io.vertx.core.buffer.Buffer

    • MEDIUMTEXT(java.lang.String

    • LONGBLOB(io.vertx.core.buffer.Buffer

    • 长文本(java.lang.String

    • 枚举(java.lang.String

    • 设定(java.lang.String

    • JSON( ,io.vertx.core.json.JsonObjectio.vertx.core.json.JsonArrayNumberBooleanStringio.vertx.sqlclient.Tuple#JSON_NULL

    存储值时,元组解码使用上述类型

    处理布尔

    在MySQL中BOOLEANBOOL数据类型是的同义词TINYINT(1)零值视为假,非零值视为真。一个BOOLEAN数据类型值存储在RowTuple作为java.lang.Byte类型,你可以调用Row#getValue来检索它的java.lang.Byte值,或者可以称之为Row#getBoolean检索它java.lang.Boolean的价值。

    client.query("SELECT graduated FROM students WHERE id = 0", ar -> {
      if (ar.succeeded()) {
        RowSet<Row> rowSet = ar.result();
        for (Row row : rowSet) {
          int pos = row.getColumnIndex("graduated");
          Byte value = row.get(Byte.class, pos);
          Boolean graduated = row.getBoolean("graduated");
        }
      } else {
        System.out.println("Failure: " + ar.cause().getMessage());
      }
    });

    当您要使用参数BOOLEAN执行准备好的语句时,只需将java.lang.Boolean添加到参数列表中即可。

    client.preparedQuery("UPDATE students SET graduated = ? WHERE id = 0", Tuple.of(true), ar -> {
      if (ar.succeeded()) {
        System.out.println("Updated with the boolean value");
      } else {
        System.out.println("Failure: " + ar.cause().getMessage());
      }
    });

    处理JSON

    MySQL JSON数据类型由以下Java类型表示:

    • String

    • Number

    • Boolean

    • io.vertx.core.json.JsonObject

    • io.vertx.core.json.JsonArray

    • io.vertx.sqlclient.Tuple#JSON_NULL 用于表示JSON空文字

    Tuple tuple = Tuple.of(
      Tuple.JSON_NULL,
      new JsonObject().put("foo", "bar"),
      3);
    
    // Retrieving json
    Object value = tuple.getValue(0); // Expect JSON_NULL
    
    //
    value = tuple.get(JsonObject.class, 1); // Expect JSON object
    
    //
    value = tuple.get(Integer.class, 2); // Expect 3
    value = tuple.getInteger(2); // Expect 3

    处理NUMERIC

    NumericJava类型用于表示MySQL的NUMERIC类型。

    Numeric numeric = row.get(Numeric.class, 0);
    if (numeric.isNaN()) {
      // Handle NaN
    } else {
      BigDecimal value = numeric.bigDecimalValue();
    }

    收集器查询

    您可以将Java收集器与查询API结合使用:

    Collector<Row, ?, Map<Long, String>> collector = Collectors.toMap(
      row -> row.getLong("id"),
      row -> row.getString("last_name"));
    
    // Run the query with the collector
    client.query("SELECT * FROM users",
      collector,
      ar -> {
        if (ar.succeeded()) {
          SqlResult<Map<Long, String>> result = ar.result();
    
          // Get the map created by the collector
          Map<Long, String> map = result.value();
          System.out.println("Got " + map);
        } else {
          System.out.println("Failure: " + ar.cause().getMessage());
        }
      });

    收集器处理不得保留引用,Row因为只有一行用于处理整个集合。

    Java Collectors提供了许多有趣的预定义收集器,例如,您可以直接从行集中轻松创建一个字符串:

    Collector<Row, ?, String> collector = Collectors.mapping(
      row -> row.getString("last_name"),
      Collectors.joining(",", "(", ")")
    );
    
    // Run the query with the collector
    client.query("SELECT * FROM users",
      collector,
      ar -> {
        if (ar.succeeded()) {
          SqlResult<String> result = ar.result();
    
          // Get the string created by the collector
          String list = result.value();
          System.out.println("Got " + list);
        } else {
          System.out.println("Failure: " + ar.cause().getMessage());
        }
      });

    MySQL存储过程

    您可以在查询中运行存储过程。结果将按照MySQL协议从服务器检索,这里没有任何魔术。

    client.query("CREATE PROCEDURE multi() BEGIN
    " +
      "  SELECT 1;
    " +
      "  SELECT 1;
    " +
      "  INSERT INTO ins VALUES (1);
    " +
      "  INSERT INTO ins VALUES (2);
    " +
      "END;", ar1 -> {
      if (ar1.succeeded()) {
        // create stored procedure success
        client.query("CALL multi();", ar2 -> {
          if (ar2.succeeded()) {
            // handle the result
            RowSet<Row> result1 = ar2.result();
            Row row1 = result1.iterator().next();
            System.out.println("First result: " + row1.getInteger(0));
    
            RowSet<Row> result2 = result1.next();
            Row row2 = result2.iterator().next();
            System.out.println("Second result: " + row2.getInteger(0));
    
            RowSet<Row> result3 = result2.next();
            System.out.println("Affected rows: " + result3.rowCount());
          } else {
            System.out.println("Failure: " + ar2.cause().getMessage());
          }
        });
      } else {
        System.out.println("Failure: " + ar1.cause().getMessage());
      }
    });

    注意:暂时不支持绑定OUT参数的预准备语句。

    MySQL的本地文件

    该客户端支持处理LOCAL INFILE请求,如果要将数据从本地文件加载到服务器中,则可以使用query LOAD DATA LOCAL INFILE '<filename>' INTO TABLE <table>;更多信息可以在MySQL参考手册中找到

    认证方式

    MySQL 8.0引入了一种新的身份验证方法caching_sha2_password,它是默认的身份验证方法为了使用这种新的身份验证方法连接到服务器,您需要使用安全连接(即启用TLS / SSL)或使用RSA密钥对交换加密的密码,以避免密码泄漏。RSA密钥对在通信过程中会自动交换,但是服务器RSA公钥在此过程中可能会遭到黑客入侵,因为它是通过不安全的连接传输的。因此,如果您的连接不安全,并且希望避免暴露服务器RSA公钥的风险,则可以如下设置服务器RSA公钥:

    MySQLConnectOptions options1 = new MySQLConnectOptions()
      .setPort(3306)
      .setHost("the-host")
      .setDatabase("the-db")
      .setUser("user")
      .setPassword("secret")
      .setServerRsaPublicKeyPath("tls/files/public_key.pem"); // configure with path of the public key
    
    MySQLConnectOptions options2 = new MySQLConnectOptions()
      .setPort(3306)
      .setHost("the-host")
      .setDatabase("the-db")
      .setUser("user")
      .setPassword("secret")
      .setServerRsaPublicKeyValue(Buffer.buffer("-----BEGIN PUBLIC KEY-----
    " +
        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3yvG5s0qrV7jxVlp0sMj
    " +
        "xP0a6BuLKCMjb0o88hDsJ3xz7PpHNKazuEAfPxiRFVAV3edqfSiXoQw+lJf4haEG
    " +
        "HQe12Nfhs+UhcAeTKXRlZP/JNmI+BGoBduQ1rCId9bKYbXn4pvyS/a1ft7SwFkhx
    " +
        "aogCur7iIB0WUWvwkQ0fEj/Mlhw93lLVyx7hcGFq4FOAKFYr3A0xrHP1IdgnD8QZ
    " +
        "0fUbgGLWWLOossKrbUP5HWko1ghLPIbfmU6o890oj1ZWQewj1Rs9Er92/UDj/JXx
    " +
        "7ha1P+ZOgPBlV037KDQMS6cUh9vTablEHsMLhDZanymXzzjBkL+wH/b9cdL16LkQ
    " +
        "5QIDAQAB
    " +
        "-----END PUBLIC KEY-----
    ")); // configure with buffer of the public key

    有关caching_sha2_password身份验证方法的更多信息,请参见《MySQL参考手册》

    使用SSL / TLS

    要配置客户端以使用SSL连接,您可以MySQLConnectOptions 像Vert.x这样进行配置NetClient支持所有SSL模式,您可以进行配置sslmodeDISABLED默认情况下,客户端处于SSL模式。 ssl参数只是设置的捷径sslmodesetSsl(true)等同于setSslMode(VERIFY_CA)setSsl(false)等同于setSslMode(DISABLED)

    MySQLConnectOptions options = new MySQLConnectOptions()
      .setPort(3306)
      .setHost("the-host")
      .setDatabase("the-db")
      .setUser("user")
      .setPassword("secret")
      .setSslMode(SslMode.VERIFY_CA)
      .setPemTrustOptions(new PemTrustOptions().addCertPath("/path/to/cert.pem"));
    
    MySQLConnection.connect(vertx, options, res -> {
      if (res.succeeded()) {
        // Connected with SSL
      } else {
        System.out.println("Could not connect " + res.cause());
      }
    });

    可以在Vert.x文档中找到更多信息

    MySQL实用程序命令

    有时您想使用MySQL实用程序命令,我们为此提供支持。可以在MySQL实用程序命令中找到更多信息

    COM_PING

    您可以使用COM_PING命令来检查服务器是否处于活动状态。如果服务器响应PING,则将通知处理程序,否则将永远不会调用该处理程序。

    connection.ping(ar -> {
      System.out.println("The server has responded to the PING");
    });

    COM_RESET_CONNECTION

    您可以使用COM_RESET_CONNECTION命令重置会话状态,这将重置连接状态,例如:-用户变量-临时表-准备好的语句

    connection.resetConnection(ar -> {
      if (ar.succeeded()) {
        System.out.println("Connection has been reset now");
      } else {
        System.out.println("Failure: " + ar.cause().getMessage());
      }
    });

    COM_CHANGE_USER

    您可以更改当前连接的用户,这将执行重新认证并重置连接状态,如COM_RESET_CONNECTION

    MySQLAuthOptions authenticationOptions = new MySQLAuthOptions()
      .setUser("newuser")
      .setPassword("newpassword")
      .setDatabase("newdatabase");
    connection.changeUser(authenticationOptions, ar -> {
      if (ar.succeeded()) {
        System.out.println("User of current connection has been changed.");
      } else {
        System.out.println("Failure: " + ar.cause().getMessage());
      }
    });

    COM_INIT_DB

    您可以使用COM_INIT_DB命令更改连接的默认架构。

    connection.specifySchema("newschema", ar -> {
      if (ar.succeeded()) {
        System.out.println("Default schema changed to newschema");
      } else {
        System.out.println("Failure: " + ar.cause().getMessage());
      }
    });

    COM_STATISTICS

    您可以使用COM_STATISTICS命令获取MySQL服务器中某些内部状态变量的可读字符串。

    connection.getInternalStatistics(ar -> {
      if (ar.succeeded()) {
        System.out.println("Statistics: " + ar.result());
      } else {
        System.out.println("Failure: " + ar.cause().getMessage());
      }
    });

    COM_DEBUG

    您可以使用COM_DEBUG命令将调试信息转储到MySQL服务器的STDOUT。

    connection.debug(ar -> {
      if (ar.succeeded()) {
        System.out.println("Debug info dumped to server's STDOUT");
      } else {
        System.out.println("Failure: " + ar.cause().getMessage());
      }
    });

    COM_SET_OPTION

    您可以使用COM_SET_OPTION命令设置当前连接的选项。目前只能CLIENT_MULTI_STATEMENTS设置。

    例如,您可以CLIENT_MULTI_STATEMENTS使用此命令禁用

    connection.setOption(MySQLSetOption.MYSQL_OPTION_MULTI_STATEMENTS_OFF, ar -> {
      if (ar.succeeded()) {
        System.out.println("CLIENT_MULTI_STATEMENTS is off now");
      } else {
        System.out.println("Failure: " + ar.cause().getMessage());
      }
    });

    MySQL和MariaDB版本支持表

    的MySQL玛丽亚数据库

    支持的

    支持的

    5.5

    10.1

    5.6

    10.2

    5.7

    10.3

    8.0

    10.4

    已知的问题:

    • 重置连接实用程序命令在MySQL 5.5、5.6和MariaDB 10.1中不起作用

    • MariaDB 10.2和10.3不支持更改用户实用程序命令

  • 相关阅读:
    Graceful degradation versus progressive enhancement
    表现与数据分离
    避免写出IE Bug
    js控制元素的显示与隐藏
    EntityManager方法简介
    JPA EntityManager详解(一)
    Springmvc中 同步/异步请求参数的传递以及数据的返回
    JPA详解
    单向关系中的JoinColumn
    Hibernate一对多和多对一关系详解 (转载)
  • 原文地址:https://www.cnblogs.com/endv/p/12032889.html
Copyright © 2020-2023  润新知