实例化一个 java 收集器 <Row, ?,List> 以从 vertx reactivate 调用准备好的语句
Instantiate a java Collector<Row, ?,List> to call prepared statements from vertx reactivate
我正在尝试使用 collector queries 读取数据库并获取对象列表。我准备了以下方法。
public <T> Future<List<T>> queryForList(String query, Tuple parameters,
Collector<Row, ?, List<T>> collector) {
Promise<List<T>> promise = Promise.promise();
this.pgPool.preparedQuery(query, parameters, collector, ar -> {
if (ar.succeeded()) {
SqlResult<List<T>> result = (SqlResult<List<T>>) ar.result();
if (result.rowCount() == 0) {
promise.complete(Collections.emptyList());
return;
}
promise.complete((List<T>)result.value());
} else {
log.warn("Query execution failed. sql: {}, message: {}",
query, ar.cause().getMessage());
promise.fail(convertPgException(ar.cause()));
}
});
return promise.future();
}
但是我在为此方法创建测试时遇到了问题。我需要定义一个收集器传递给以下测试用例,但无法在以下测试行中实例化收集器。
@Test
public void returnsAsListUsingCollectors(TestContext ctx) {
Collector<Row, ?, List<Temp>> collector = Collector.of(
DataCollector::list,
DataCollector::accept,
DataCollector::combine,
DataMapper::apply,
DataCollector::charactoristics);
this.subject.queryForList("select id,data from test_table where id in (, )",
Tuple.of(1, 2), collector)
.setHandler(ctx.asyncAssertSuccess(res -> {
//verification of elements
}));
}
以下方法用于数据收集和数据映射。我收到 "Can not resolve apply" 编译错误。
class DataMapper implements Function {
@Override
public Object apply(Object o) {
String data = ((Row)o).getString("data");
String extra = ((Row)o).getString("extra");
return new Temp(extra, data);
}
}
class Temp {
String extra;
String data;
public Temp(String extra, String data){
this.data = data;
this.extra = extra;
}
}
class DataCollector {
private List<Temp> tempList = new ArrayList<>();
public void accept(Temp o) {
tempList.add(o);
}
DataCollector combine(DataCollector collector){
this.tempList.addAll(collector.list());
return this;
}
public List<Temp> list(){
return this.tempList;
}
public Set<Collector.Characteristics> charactoristics(){
return Collections.emptySet();
}
}
让我们从这里开始慢慢来。首先,制作原始的 类 总是一个糟糕的主意,如果你 知道 你正在从 Row
转换为 Temp
,请将其指定为这样:
static class DataMapper implements Function<Row, Temp> {
@Override
public Temp apply(Row o) {
String data = o.getString("data");
String extra = o.getString("extra");
return new Temp(extra, data);
}
}
不过,您很快就会发现,您并不真正需要这个 implements
部分,它可以像这样简单:
static class DataMapper {
public static Temp apply(Row o) {
String data = o.getString("data");
String extra = o.getString("extra");
return new Temp(extra, data);
}
}
然后,养成在构造函数中将字段声明为 final
的好习惯:
static class Temp {
private final String extra;
private final String data;
public Temp(String extra, String data) {
this.data = data;
this.extra = extra;
}
}
您遇到的主要问题是定义此自定义收集器并且您使事情过于复杂。如果你想使用 Collector::of
- 你必须查看它对 Row, ? List<Temp>
的定义。这基本上是说:我将接受一些 Row
s(一次打开)作为输入并将它们转换为 List<Temp>
。这几乎就是 you 关心的全部内容。因此,您的收集器可以简单地定义为:
Collector<Row, ?, List<Temp>> collector =
Collector.of(ArrayList::new,
(list, element) -> list.add(DataMapper.apply(element)),
(left, right) -> {
left.addAll(right);
return left;
},
Characteristics.IDENTITY_FINISH
);
我正在尝试使用 collector queries 读取数据库并获取对象列表。我准备了以下方法。
public <T> Future<List<T>> queryForList(String query, Tuple parameters,
Collector<Row, ?, List<T>> collector) {
Promise<List<T>> promise = Promise.promise();
this.pgPool.preparedQuery(query, parameters, collector, ar -> {
if (ar.succeeded()) {
SqlResult<List<T>> result = (SqlResult<List<T>>) ar.result();
if (result.rowCount() == 0) {
promise.complete(Collections.emptyList());
return;
}
promise.complete((List<T>)result.value());
} else {
log.warn("Query execution failed. sql: {}, message: {}",
query, ar.cause().getMessage());
promise.fail(convertPgException(ar.cause()));
}
});
return promise.future();
}
但是我在为此方法创建测试时遇到了问题。我需要定义一个收集器传递给以下测试用例,但无法在以下测试行中实例化收集器。
@Test
public void returnsAsListUsingCollectors(TestContext ctx) {
Collector<Row, ?, List<Temp>> collector = Collector.of(
DataCollector::list,
DataCollector::accept,
DataCollector::combine,
DataMapper::apply,
DataCollector::charactoristics);
this.subject.queryForList("select id,data from test_table where id in (, )",
Tuple.of(1, 2), collector)
.setHandler(ctx.asyncAssertSuccess(res -> {
//verification of elements
}));
}
以下方法用于数据收集和数据映射。我收到 "Can not resolve apply" 编译错误。
class DataMapper implements Function {
@Override
public Object apply(Object o) {
String data = ((Row)o).getString("data");
String extra = ((Row)o).getString("extra");
return new Temp(extra, data);
}
}
class Temp {
String extra;
String data;
public Temp(String extra, String data){
this.data = data;
this.extra = extra;
}
}
class DataCollector {
private List<Temp> tempList = new ArrayList<>();
public void accept(Temp o) {
tempList.add(o);
}
DataCollector combine(DataCollector collector){
this.tempList.addAll(collector.list());
return this;
}
public List<Temp> list(){
return this.tempList;
}
public Set<Collector.Characteristics> charactoristics(){
return Collections.emptySet();
}
}
让我们从这里开始慢慢来。首先,制作原始的 类 总是一个糟糕的主意,如果你 知道 你正在从 Row
转换为 Temp
,请将其指定为这样:
static class DataMapper implements Function<Row, Temp> {
@Override
public Temp apply(Row o) {
String data = o.getString("data");
String extra = o.getString("extra");
return new Temp(extra, data);
}
}
不过,您很快就会发现,您并不真正需要这个 implements
部分,它可以像这样简单:
static class DataMapper {
public static Temp apply(Row o) {
String data = o.getString("data");
String extra = o.getString("extra");
return new Temp(extra, data);
}
}
然后,养成在构造函数中将字段声明为 final
的好习惯:
static class Temp {
private final String extra;
private final String data;
public Temp(String extra, String data) {
this.data = data;
this.extra = extra;
}
}
您遇到的主要问题是定义此自定义收集器并且您使事情过于复杂。如果你想使用 Collector::of
- 你必须查看它对 Row, ? List<Temp>
的定义。这基本上是说:我将接受一些 Row
s(一次打开)作为输入并将它们转换为 List<Temp>
。这几乎就是 you 关心的全部内容。因此,您的收集器可以简单地定义为:
Collector<Row, ?, List<Temp>> collector =
Collector.of(ArrayList::new,
(list, element) -> list.add(DataMapper.apply(element)),
(left, right) -> {
left.addAll(right);
return left;
},
Characteristics.IDENTITY_FINISH
);