java - 准备好的语句可以开箱即用吗?

标签 java spring-boot cassandra scylla

我想在我的应用程序中执行 CQL 时使用准备好的语句。此功能看起来是由 ReactiveCqlTemplate 类提供的,我已将其传递到我的 Cassandra 配置中的 ReactiveCassandraTemplate 中:

@Configuration
@EnableReactiveCassandraRepositories(
        basePackages = "com.my.app",
        includeFilters = {
                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {ScyllaPersonRepository.class})
        })
public class CassandraConfiguration extends AbstractReactiveCassandraConfiguration {

    @Value("${cassandra.host}")
    private String cassandraHost;

    @Value("${cassandra.connections}")
    private Integer cassandraConnections;

    @Override
    public CassandraClusterFactoryBean cluster() {
        PoolingOptions poolingOptions = new PoolingOptions()
                .setCoreConnectionsPerHost(HostDistance.LOCAL,  cassandraConnections)
                .setMaxConnectionsPerHost(HostDistance.LOCAL, cassandraConnections*2);

        CassandraClusterFactoryBean bean = super.cluster();
        bean.setJmxReportingEnabled(false);
        bean.setPoolingOptions(poolingOptions);
        bean.setLoadBalancingPolicy(new TokenAwarePolicy(new RoundRobinPolicy()));

        return bean;
    }

    @Override
    public ReactiveCassandraTemplate reactiveCassandraTemplate() {
        return new ReactiveCassandraTemplate(reactiveCqlTemplate(), cassandraConverter());
    }

    @Bean
    public CassandraEntityInformation getCassandraEntityInformation(CassandraOperations cassandraTemplate) {
        CassandraPersistentEntity<Person> entity =
                (CassandraPersistentEntity<Person>)
                        cassandraTemplate
                                .getConverter()
                                .getMappingContext()
                                .getRequiredPersistentEntity(Person.class);
        return new MappingCassandraEntityInformation<>(entity, cassandraTemplate.getConverter());
    }

    @Override
    public SchemaAction getSchemaAction() {
        return SchemaAction.CREATE_IF_NOT_EXISTS;
    }

    public String getContactPoints() {
        return cassandraHost;
    }

    public String getKeyspaceName() {
        return "mykeyspace";
    }
}

这是我的 Cassandra 配置过滤器中引用的 ScyllaPersonRepository

public interface ScyllaPersonRepository extends ReactiveCassandraRepository<Person, PersonKey> {
    @Query("select id, name from persons where id = ?0")
    Flux<Object> findPersonById(@Param("id") String id);
}

执行一些查询后,我的 Scylla Monitoring Dashboard 中的 CQL 非准备语句指标表明我根本没有使用准备好的语句。

在遵循文档 here 之后,我能够使用准备好的语句它引导我自己创建了 CQL

public class ScyllaPersonRepository extends SimpleReactiveCassandraRepository<Person, PersonKey> {
    private final Session session;
    private final CassandraEntityInformation<Person, PersonKey> entityInformation;
    private final ReactiveCassandraTemplate cassandraTemplate;
    private final PreparedStatementCache cache = PreparedStatementCache.create();

    public ScyllaPersonRepository(
            Session session,
            CassandraEntityInformation<Person, PersonKey> entityInformation,
            ReactiveCassandraTemplate cassandraTemplate
    ) {
        super(entityInformation, cassandraTemplate);
        this.session = session;
        this.entityInformation = entityInformation;
        this.cassandraTemplate = cassandraTemplate;
    }

    public Flux<ScyllaUser> findSegmentsById(String id) {
        return cassandraTemplate
                .getReactiveCqlOperations()
                .query(
                        findPersonByIdQuery(id),
                        (row, rowNum) -> convert(row)
                );
    }

    private BoundStatement findPersonByIdQuery(String id) {
        return CachedPreparedStatementCreator.of(
                cache,
                QueryBuilder.select()
                        .column("id")
                        .column("name")
                        .from("persons")
                        .where(QueryBuilder.eq("id", QueryBuilder.bindMarker("id"))))
                .createPreparedStatement(session)
                .bind()
                .setString("id", id);
    }

    private Person convert(Row row) {
        return new Person(
                row.getString("id"),
                row.getString("name"));
    }
}

但是,我真的希望 ORM 为我处理这一切。是否可以开箱即用地配置此行为,这样我就不需要自己手动编写 CQL,而只需在我的 Cassandra 配置中将其作为一个选项启用,并让 ORM 进行编排这一切都在幕后?

最佳答案

坦率地说,我认为这是一个错误(请求增强),应该在 Springs Jira 中提交。 似乎存储库根本不支持开箱即用(我也没有找到任何配置选项如何翻转它,但我可能错过了它)。

其实我的理论是正确的: https://jira.spring.io/projects/DATACASS/issues/DATACASS-578?filter=allopenissues 所以只需添加您自己并尝试向他们寻求解决方案。

关于java - 准备好的语句可以开箱即用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62267829/

相关文章:

java - 在java中使用itext格式化pdfptables

java - 数组用0初始化

java - 用于单元测试的 Cassandra 2.1 设置?

java - 在 cassandra 中设置 TTL 后无法运行选择查询

Cassandra 数据存储大小

java - 拆分字符串在 java 中不起作用无法导入 `split`

java - 一个变量破坏另一个变量

maven - Camel Spring Boot Maven到Gradle

spring-boot - 为什么 SpringFox 不暴露@RepositoryRestResource?

authentication - Spring boot Ldap 身份验证失败,LDAP 错误代码 49 - 80090308 数据 52e