如何使用同步和异步方法正确处理 DataStax 访问器?

How to cook right a DataStax accessor with sync and async methods?

当我为实体编写 accessor 时,我通常会添加同一查询的同步和异步版本。例如:

@Accessor
public interface SourceDataAccessor {
      @Query("select * from source_data where data_id = ?")
      Result<SourceDataCass> get(UUID dataId);

      @Query("select * from source_data where data_id = ?")
      ListenableFuture<Result<SourceDataCass>> getAsync(UUID dataId);
}

但是当访问器被实例化时,日志中会出现这样的警告:

12:32:49,793  WARN com.datastax.driver.core.Cluster:2109 - Re-preparing already prepared query select * from source_data where data_id = ?. Please note that preparing the same query more than once is generally an anti-pattern and will likely affect performance. Consider preparing the statement only once.

可能有一种方法可以同时拥有同一查询的同步和异步版本,但无需重新准备?

这是一个有趣的用例。

目前我们不支持它,因此解决方法是仅使用异步方法编写访问器,然后使用 getAsync().getUninterruptibly() 作为同步版本(这是内部完成的方式)。我同意它不是很用户友好,您可以使用包装器 class 来完成它,但这仍然是一个额外的步骤。

我们可以很容易地做的一件事是在处理方法时缓存准备好的语句,因此至少在同一接口内重复查询时不会准备两次。

请开一个JIRA ticket if you're interested to see this in the driver. If you feel like fixing it yourself, you can also create a pull request (from a quick look, the only method to change is AccessorMapper#prepare).

您可以将访问器更改为 return a Statement

@Accessor
public interface SourceDataAccessor {
  @Query("select * from source_data where data_id = ?")
  Statement get(UUID dataId);
}

然后使用

执行语句
ResultSet rs = session.execute(statement);

ResultSetFuture rsf = session.executeAsync(statement);

为了将结果集映射到您的 class,您可以使用映射器

MappingManager mappingManager = new MappingManager(session);
Mapper mapper = mappingManager.mapper(SourceDataCass.class);
Result<SourceDataClass> sourceDataClass = mapper.map(rs);