实例化一个 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> 的定义。这基本上是说:我将接受一些 Rows(一次打开)作为输入并将它们转换为 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
 );