Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Datastax Cassandra驱动程序时是否重新使用PreparedStatement?_Java_Cassandra_Datastax Java Driver - Fatal编程技术网

Java 使用Datastax Cassandra驱动程序时是否重新使用PreparedStatement?

Java 使用Datastax Cassandra驱动程序时是否重新使用PreparedStatement?,java,cassandra,datastax-java-driver,Java,Cassandra,Datastax Java Driver,我目前正在使用Cassandra 2的Datastax Cassandra驱动程序来执行cql3。这是正确的。我开始使用PreparedStatement的: Session session = sessionProvider.getSession(); try { PreparedStatement ps = session.prepare(cql); ResultSet rs = session.execute(ps.bind(objects)); if (irsr

我目前正在使用Cassandra 2的Datastax Cassandra驱动程序来执行cql3。这是正确的。我开始使用
PreparedStatement的

Session session = sessionProvider.getSession();
try {
    PreparedStatement ps = session.prepare(cql);
    ResultSet rs = session.execute(ps.bind(objects));
    if (irsr != null) {
       irsr.read(rs);
    }
}
有时我会在日志中收到来自驱动程序的警告:

Re-preparing already prepared query . 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.
这个警告很有道理,但我不确定应该如何重用
PreparedStatement

我应该在构造函数/init方法中创建所有
PreparedStatement
,而不是简单地使用它们吗


但是,当多个线程同时使用相同的
PreparedStatement
时(特别是调用
PreparedStatement.bind()
来绑定对象),这是否很好呢?

您可以只初始化PreparedStatement一次,并在应用程序运行时缓存它。只要Cassandra集群启动,它就应该可用

使用来自多个线程的语句是可以的(只要不通过
setXXX()
方法修改它)。调用bind()时,下面的代码只读取PreparedStatement,然后创建BoundStatement()的新实例,然后调用线程可以自由地对其进行修改


,如果您好奇的话(搜索
bind()
)。

我们正在Spring的Web应用程序中使用cassandra。在我们的例子中,我们在安装封装针对cf(我们的存储库)的操作的bean时创建PreparedStatements

下面是我们正在使用的代码片段:

@Repository
public class StatsRepositoryImpl implements StatsRepository {

@SuppressWarnings("unused")
    @PostConstruct
    private void initStatements(){
        if (cassandraSession == null){
            LOG.error("Cassandra 2.0 not available");
        } else {
            GETSTATS_BY_PROJECT = cassandraSession.prepare(SELECTSTATS+" WHERE projectid = ?");
        }

    }       

@Override
    public Stats findByProject(Project project) {
        Stats stats = null;

        BoundStatement boundStatement = new BoundStatement(GETSTATS_BY_PROJECT);

        ResultSet rs = cassandraSession.execute(boundStatement.bind(project.getId()));
        for (Row row : rs){
            stats = mapRowToStats(row);
        }

        return stats;
    } 

通过这种方式,每次执行findByProject方法时都会重用准备好的语句

如果密钥空间固定,上述解决方案将起作用。在多租户情况下,此解决方案将无法满足要求。我只是按照下面的方式做了,其中keyspace作为参数传递

检查prepared语句中的keyspace,如果它与传递的参数相同,则不要准备语句,因为在本例中它已经准备好了

 private BatchStatement eventBatch(List<SomeEvent> events, String keySpace) {

    BatchStatement batch = new BatchStatement();
    String preparedStmtKeySpace = propEventPer == null? "" : propEventPer.getQueryKeyspace();
    if(!keySpace.equals("\"" + preparedStmtKeySpace +  "\"")) {
        eventStmt = cassandraOperations.getSession().prepare(colFamilyInsert(keySpace + "." + "table_name"));

    }
    ....
private RegularStatement colFamilyInsert(String colFamilyName) {
    return insertInto(colFamilyName)
            .value(PERSON_ID, bindMarker())
            .value(DAY, bindMarker());

}
private BatchStatement eventBatch(列出事件、字符串键空间){
BatchStatement batch=新的BatchStatement();
字符串preparedStmtKeySpace=propEventPer==null?”:propEventPer.getQueryKeyspace();
如果(!keySpace.equals(“\”+preparedStmtKeySpace+“\”)){
eventStmt=cassandraOperations.getSession().prepare(colFamilyInsert(keySpace+“+”table_name”);
}
....
私人定期声明colFamilyInsert(字符串colFamilyName){
返回insertInto(colFamilyName)
.value(PERSON\u ID,bindMarker())
.值(天,bindMarker());
}
创建PreparedStatement对象池,每个CQL查询一个

然后,当客户端请求这些查询时,通过调用
bind()
获取相应的缓存PS对象并提供值


正如Daniel所解释的,
bind()
newboundstmt(param)
这使这个线程安全。

感谢Daniel的回复。调用bind时创建并返回BoundStatement解释了一切,现在我可以正确使用preparedstatements,而不用担心。为在使用prepared statements的最佳实践的基础上扩展一个基于spring的示例干杯。何时关闭Cassandra会议?你在哪里关闭过?
03-Apr-2017 10:02:24,120 WARN  [com.datastax.driver.core.Cluster] (cluster1-worker-2851) Re-preparing already prepared query is generally an anti-pattern and will likely affect performance. Consider preparing the statement only once. Query='select * from xxxx where cjpid=? and cjpsnapshotid =?'