SQL Client Templates
SQL Client Templates 是一个被设计为方便执行SQL查询的小型库
使用方法
使用SQL Client Templates前请将以下依赖加入你的项目中
- Maven (在你的
pom.xml中):
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-sql-client-templates</artifactId>
<version>4.0.0.Beta3</version>
</dependency>
- Gradle (在
build.gradle文件中):
dependencies {
implementation 'io.vertx:vertx-sql-client-templates:4.0.0.Beta3'
}
开始
下面是最简单使用SQL 模板的方法
一个SQL模板使用带名字的参数,因此它在默认情况下使用map而不是tuple作为参数源
一个SQL模板默认情况下会生成一个RowSet<Row>就像client中的PreparedQuery方法做的那样。事实上模板只是PreparedQuery的一层薄封装
(译者:类似于mybatis)
Map<String, Object> parameters = Collections.singletonMap("id", 1);
SqlTemplate
.forQuery(client, "SELECT * FROM users WHERE id=#{id}")
.execute(parameters)
.onSuccess(users -> {
users.forEach(row -> {
System.out.println(row.getString("first_name") + " " + row.getString("last_name"));
});
});
当你需要执行insert或者update操作而且你并不关心结果时,你可以使用SqlTemplate.forUpdate做替代
Map<String, Object> parameters = new HashMap<>();
parameters.put("id", 1);
parameters.put("firstName", "Dale");
parameters.put("lastName", "Cooper");
SqlTemplate
.forUpdate(client, "INSERT INTO users VALUES (#{id},#{firstName},#{lastName})")
.execute(parameters)
.onSuccess(v -> {
System.out.println("Successful update");
});
模板语法
模板语法使用#{XXX}语法,其中XXX是一个有效的java标识符字符串(没有关键字限制)。
您可以使用\来转义,比如说\{foo}会被解释为#{foo}字符串而不是foo`参数。
(译者:就是直接获取#{foo},而不是会被替换为?再替换为实际值)
行映射
一般情况下模板会产生Row作为结果类型
你也可以提供一个函数实现行级别的映射
Function<Row, User> ROW_USER_MAPPER = row -> {
User user = new User();
user.id = row.getInteger("id");
user.firstName = row.getString("firstName");
user.lastName = row.getString("lastName");
return user;
};
实现行级别映射
SqlTemplate
.forQuery(client, "SELECT * FROM users WHERE id=#{id}")
.mapTo(ROW_USER_MAPPER)
.execute(Collections.singletonMap("id", 1))
.onSuccess(users -> {
users.forEach(user -> {
System.out.println(user.firstName + " " + user.lastName);
});
});
参数映射
模板可以使用Map<String,Object>作为默认输入
你可以提供这样一个函数
Function<User, Map<String, Object>> PARAMETERS_USER_MAPPER = user -> {
Map<String, Object> parameters = new HashMap<>();
parameters.put("id", user.id);
parameters.put("firstName", user.firstName);
parameters.put("lastName", user.lastName);
return parameters;
};
实现参数映射
User user = new User();
user.id = 1;
user.firstName = "Dale";
user.firstName = "Cooper";
SqlTemplate
.forUpdate(client, "INSERT INTO users VALUES (#{id},#{firstName},#{lastName})")
.mapFrom(PARAMETERS_USER_MAPPER)
.execute(user)
.onSuccess(res -> {
System.out.println("User inserted");
});
你也可以这样执行批量操作
SqlTemplate
.forUpdate(client, "INSERT INTO users VALUES (#{id},#{firstName},#{lastName})")
.mapFrom(PARAMETERS_USER_MAPPER)
.executeBatch(users)
.onSuccess(res -> {
System.out.println("Users inserted");
});
使用Jackson databind进行映射
你可以使用Jackson databind功能进行映射
你需要把jackson databind依赖加入你的项目
- Maven (in your
pom.xml):
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
- Gradle (in your
build.gradlefile):
dependencies {
compile 'com.fasterxml.jackson.core:jackson-databind:${jackson.version}'
}
通过使用行键值对的JsonObject实现行级别的映射,然会调用mapTo方法使用Jackson databind将行结果映射为任意的java类型
SqlTemplate
.forQuery(client, "SELECT * FROM users WHERE id=#{id}")
.mapTo(User.class)
.execute(Collections.singletonMap("id", 1))
.onSuccess(users -> {
users.forEach(user -> {
System.out.println(user.firstName + " " + user.lastName);
});
});
同样,参数映射是通过使用JsonObject.mapFrom将对象映射到JsonObject来实现的。然后使用键/值对生成模板参数。
User u = new User();
u.id = 1;
SqlTemplate
.forUpdate(client, "INSERT INTO users VALUES (#{id},#{firstName},#{lastName})")
.mapFrom(User.class)
.execute(u)
.onSuccess(res -> {
System.out.println("User inserted");
});
Java Date/Time 映射的API
你可以使用jackson-modules-java8的Jackson拓展来映射java.time类型
你需要将Jackson JSR 31 datatype依赖加入你的依赖
- Maven (in your
pom.xml):
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
- Gradle (in your
build.gradlefile):
dependencies {
compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${jackson.version}'
}
然后你可以将time模块注册到Jackson ObjectMapper中
ObjectMapper mapper = io.vertx.core.json.jackson.DatabindCodec.mapper();
mapper.registerModule(new JavaTimeModule());
你现在可以使用LocalDateTime这样的java.time类型了
public class LocalDateTimePojo {
public LocalDateTime localDateTime;
}
使用Vert.x data objects进行映射
SQL Client Template组件可以为Vert.x data objects生成映射函数
一个Vert.x data objects就是一个被标注@DataObject注解的java bean
@DataObject
class UserDataObject {
private long id;
private String firstName;
private String lastName;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
代码生成
任何被@RowMapped或者@ParamtersMapped注解的data objectd都会触发生成相应的映射类
codegen注解处理器在编译期生成这些类。这是Java编译器的一个特性,因此不需要额外的步骤,只需要正确配置
只要添加io.vertx:vertx-codegen:processor和io.vertx:vertx-sql-client-templates到你的项目中
下面是使用Maven配置的例子
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-codegen</artifactId>
<version>4.0.0.Beta3</version>
<classifier>processor</classifier>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-sql-client-templates</artifactId>
<version>4.0.0.Beta3</version>
</dependency>
这个特性也可以在Gradle中使用
annotationProcessor "io.vertx:vertx-codegen:4.0.0.Beta3:processor"
compile "io.vertx:vertx-sql-client-templates:4.0.0.Beta3"
IDE一般会提供这些注解处理器的支持
codegen处理器分类器通过META-INF/services插件机制将服务代理注解处理器的自动配置添加到jar中。
如果你想,你也可以常规的jar中使用它,但你需要显式声明注释处理器,例如在Maven:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessors>
<annotationProcessor>io.vertx.codegen.CodeGenProcessor</annotationProcessor>
</annotationProcessors>
</configuration>
</plugin>
行映射
你可以通过给你的data object 添加 @RowMapped注解生成行映射
@DataObject
@RowMapped
class UserDataObject {
private long id;
private String firstName;
private String lastName;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
You can use custom names thanks to the @Column annotation.
默认情况下,每个列名都绑定在数据对象属性之后,例如userName字段会绑定到userName列
你可以使用自定义列名通过使用@Column注解
@DataObject
@RowMapped
class UserDataObject {
private long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
你可以将注解标识在字段,getter,setter方法上
生成的映射器可以用来执行行映射,如行映射一章中所解释的。
SqlTemplate
.forQuery(client, "SELECT * FROM users WHERE id=#{id}")
.mapTo(UserDataObjectRowMapper.INSTANCE)
.execute(Collections.singletonMap("id", 1))
.onSuccess(users -> {
users.forEach(user -> {
System.out.println(user.getFirstName() + " " + user.getLastName());
});
});
参数映射
你也可通过用@ParametersMapped注解你的data object来生成参数映射
@DataObject
@ParametersMapped
class UserDataObject {
private long id;
private String firstName;
private String lastName;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
默认情况下,每个参数都绑定在数据对象属性之后,比如userName字段就绑定到userName参数
你也可以通过@TemplateParameter注解自定义名字
@DataObject
@ParametersMapped
class UserDataObject {
private long id;
@TemplateParameter(name = "first_name")
private String firstName;
@TemplateParameter(name = "last_name")
private String lastName;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
你可以将注解标识在字段,getter,setter方法上
生成的映射器可以用来执行行映射,如参数映射一章中所解释的。
UserDataObject user = new UserDataObject().setId(1);
SqlTemplate
.forQuery(client, "SELECT * FROM users WHERE id=#{id}")
.mapFrom(UserDataObjectParamMapper.INSTANCE)
.execute(user)
.onSuccess(users -> {
users.forEach(row -> {
System.out.println(row.getString("firstName") + " " + row.getString("lastName"));
});
});
java枚举类型映射
当你使用的SQL客户端支持的时候,你可以使用java枚举类的映射(比如,Reactive PostgreSQL client)
通常Java枚举类型被映射到字符串/数字和可能的自定义数据库枚举类型。
命名格式
默认情况下模板的参数和列名相同
你可以重写Column和TemplateParameter注解中的默认名称,并使用您喜欢的格式。
你还可以在Rowmapped和ParametersMapped注解中配置映射器的特定格式化用例
@DataObject
@RowMapped(formatter = SnakeCase.class)
@ParametersMapped(formatter = QualifiedCase.class)
class UserDataObject {
// ...
}
下面是可以使用的例子
CamelCase:FirstNameLowerCamelCase:firstName-类似于驼峰,但是是以小写开头,这是默认使用的SnakeCase:first_nameKebabCase:first-nameQualifiedCase:first.name