Reactive MySQL
客户端是MySQL
的客户端,其API
专注于可伸缩性和低开销。
产品特点
添加依赖Reactive MySQL Client
pom.xml
):<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-mysql-client</artifactId>
</dependency>
build.gradle
文件中):dependencies {
compile 'io.vertx:vertx-mysql-client:4.0.1-SNAPSHOT'
}
连接MySQL
做一个简单的查询
MySQLConnectOptions connectOptions = new MySQLConnectOptions()
.setPort(3306)
.setHost("127.0.0.1")
.setDatabase("myschool")
.setUser("root")
.setPassword("123456");
// Pool options
PoolOptions poolOptions = new PoolOptions()
.setMaxSize(5);
// 连接池
MySQLPool pool = MySQLPool.pool(vertx, connectOptions, poolOptions);
// A simple query
pool.query("SELECT * FROM student WHERE id='1'")
.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();
});
官方文挡调用的是static MySQLPool pool(MySQLConnectOptions connectOptions, PoolOptions poolOptions)
创建连接的方法不可行,所以使用static MySQLPool pool(Vertx vertx, MySQLConnectOptions connectOptions, PoolOptions poolOptions)
具体原因还没有查到
不再需要连接池时,需要释放它:
pool.close();
也可以使用URl
连接MySQL
mysql://dbuser:secretpassword@database.server.com:3211/mydb
或者还可以根据连接属性,默认覆盖客户端的属性
connectOptions
// 设置重新连接尝试的值
.setReconnectAttempts(2)
// 设置重新连接间隔
.setReconnectInterval(1000);
// 增
pool.preparedQuery("INSERT INTO student (id, name) VALUES (?, ?)")
.execute(Tuple.of("3", "刘备"), ar -> {
if (ar.succeeded()) {
RowSet<Row> rows = ar.result();
System.out.println(rows.rowCount());
} else {
System.out.println("Failure: " + ar.cause().getMessage());
}
});
// 删
pool.preparedQuery("DELETE FROM student where id = ?")
.execute(Tuple.of("3"), ar -> {
if (ar.succeeded()) {
RowSet<Row> rows = ar.result();
System.out.println(rows.rowCount());
} else {
System.out.println("Failure: " + ar.cause().getMessage());
}
});
// 改
pool.preparedQuery("UPDATE student SET name = ? where id = ?")
.execute(Tuple.of("刘备update","3"), ar -> {
if (ar.succeeded()) {
RowSet<Row> rows = ar.result();
System.out.println(rows.rowCount());
} else {
System.out.println("Failure: " + ar.cause().getMessage());
}
});
使用池时,可以调用withConnection
将连接中执行的函数传递给池。它从池中借用一个连接,并使用该连接调用函数。该函数必须返回任意结果。将完成后,连接将返回到池中,并提供总体结果。
pool.withConnection(connection ->
connection
.preparedQuery("INSERT INTO student (id,name) VALUES (?, ?)")
.executeBatch(Arrays.asList(
Tuple.of("3", "刘备"),
Tuple.of("4", "关羽")
))
.compose(res -> connection
// Do something with rows
.query("SELECT COUNT(*) FROM student")
.execute()
.map(rows -> rows.iterator().next().getInteger(0)))
).onSuccess(count -> {
System.out.println("Insert student now the number of student is " + count);
});
您可以使用SQL BEGIN
、COMMIT
执行事务ROLLBACK
,如果这样做,则必须使用SqlConnection
和自己进行管理。
pool.getConnection()
// 事务必须使用连接
.onSuccess(conn -> {
// 事务开始
conn.begin()
.compose(tx -> conn
.query("INSERT INTO student (id, name) VALUES ('5','曹操')")
.execute()
.compose(res2 -> conn
.query("INSERT INTO student (id, name) VALUES ('6','司马懿')")
.execute())
// 提交事务
.compose(res3 -> tx.commit()))
// 将连接返回到连接池里面
.eventually(v -> conn.close())
.onSuccess(v -> System.out.println("Transaction succeeded"))
.onFailure(err -> System.out.println("Transaction failed: " + err.getMessage()));
});
使用池时,可以调用withTransaction
将在事务中执行的函数传递给池。它从池中借用一个连接,开始事务,并在执行此事务范围内所有操作的客户端上调用该函数。该函数必须返回任意结果的未来:
事务完成后,连接将返回到池中,并提供总体结果。
pool.withTransaction(client -> client
.query("INSERT INTO student (id, name) VALUES ('5','曹操')")
.execute()
.flatMap(res -> client
.query("INSERT INTO student (id, name) VALUES ('6','司马懿')")
.execute()
// Map to a message result
.map("student inserted")))
.onSuccess(v -> System.out.println("Transaction succeeded"))
.onFailure(err -> System.out.println("Transaction failed: " + err.getMessage())
);
SQL客户端模板是一个小型库,旨在帮助执行SQL查询。
添加依赖SQL Client Templates
pom.xml
):<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-sql-client-templates</artifactId>
</dependency>
build.gradle
文件中):dependencies {
implementation 'io.vertx:vertx-sql-client-templates:4.0.1-SNAPSHOT'
}
简单查询:SQL模板使用命名参数,因此(默认情况下)将映射用作参数源。
一个SQL模板(默认情况下)会产生RowSet
一个client PreparedQuery
。实际上,模板是的薄包装PreparedQuery
。
Map<String, Object> parameters = Collections.singletonMap("id", 1);
SqlTemplate
.forQuery(pool, "SELECT * FROM student WHERE id=#{id}")
.execute(parameters)
.onSuccess(stu -> {
stu.forEach(row -> {
System.out.println(row.getString("id") + " " + row.getString("name"));
});
});
需要执行插入或更新操作而无需关心结果时,可以使用SqlTemplate.forUpdate
Map<String, Object> parameters = new HashMap<>();
parameters.put("id", "7");
parameters.put("name", "曹植");
SqlTemplate
.forUpdate(pool, "UPDATE student set name=#{name} where id= #{id}")
.execute(parameters)
.onSuccess(v -> {
System.out.println("Successful update");
});
RowMapper<Student> ROW_STUDENT_MAPPER = row -> {
Student student = new Student();
student.setId(row.getString("id"));
student.setName(row.getString("name"));
return student;
};
Map<String, Object> parameters = Collections.singletonMap("id", 1);
SqlTemplate
.forQuery(pool, "SELECT * FROM student WHERE id=#{id}")
.mapTo(ROW_STUDENT_MAPPER)
.execute(parameters)
.onSuccess(students -> {
students.forEach(student -> {
System.out.println(student.getId() + " " + student.getName());
});
});
Anemic JSON行映射是使用以下命令在模板行列和JSON对象之间进行的简单映射 toJson
SqlTemplate
.forQuery(pool, "SELECT * FROM student WHERE id=#{id}")
.mapTo(Row::toJson)
.execute(Collections.singletonMap("id", 1))
.onSuccess(users -> {
users.forEach(user -> {
System.out.println(user.encode());
});
});
TupleMapper<Student> PARAMETERS_STUDENT_MAPPER = TupleMapper.mapper(user -> {
Map<String, Object> parameters = new HashMap<>();
parameters.put("id", user.getId());
parameters.put("name", user.getName());
return parameters;
});
Student student = new Student();
student.setId("10");
student.setName("周瑜");
SqlTemplate
.forUpdate(pool, "INSERT INTO student (id, name) VALUES (#{id}, #{name})")
.mapFrom(PARAMETERS_STUDENT_MAPPER)
.execute(student)
.onSuccess(res -> {
System.out.println("Student inserted");
});
JsonObject stu = new JsonObject();
stu.put("id", "11");
stu.put("name", "赵子龙");
SqlTemplate
.forUpdate(pool, "INSERT INTO student (id, name) VALUES (#{id},#{name})")
.mapFrom(TupleMapper.jsonObject())
.execute(stu)
.onSuccess(res -> {
System.out.println("Student inserted");
});
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
</dependency>
这个Jackson
的版本有点问题,最新的版本引用不生效,找到一个别人测试过的版本
SqlTemplate
.forQuery(pool, "SELECT * FROM student WHERE id=#{id}")
.mapTo(Student.class)
.execute(Collections.singletonMap("id", 1))
.onSuccess(students -> {
students.forEach(student -> {
System.out.println(student.getId() + " " + student.getName());
});
})
.onFailure(event -> {
System.out.println(event.getMessage());
});
Vert.x
操作MySQL
数据库,从代码上看是要比Java
难理解一点,看了很久,用的话就比较简单,但是在实际操作上可能还有很多需要注意的地方。
最近不是很忙,但是却没那么想学习了,估计是最近有点疲累,可是又什么都没有做,心理上的疲累,比实际的疲累还要难受。也有可以是最近太过放飞自我,没有学习观念,得赶紧恢复一下状态。
兄弟们各自加油了,先溜为上!