Java 如何为同一查询字符串获取两个PreparedStatement对象
我们有一个用例,需要为同一查询字符串提供两个单独的PreparedStatement对象(一个带有RetryPolicy,另一个没有任何重试策略)。 当我们尝试创建两个单独的PreparedStatement时,只会看到一个PreparedStatement被保留(前一个PreparedStatement被最后一个PreparedStatement覆盖)。我们查看了代码实现,发现方法Java 如何为同一查询字符串获取两个PreparedStatement对象,java,cassandra,Java,Cassandra,我们有一个用例,需要为同一查询字符串提供两个单独的PreparedStatement对象(一个带有RetryPolicy,另一个没有任何重试策略)。 当我们尝试创建两个单独的PreparedStatement时,只会看到一个PreparedStatement被保留(前一个PreparedStatement被最后一个PreparedStatement覆盖)。我们查看了代码实现,发现方法Cluster.addPrepared正在查看查询的某种MD5哈希,它用新的PreparedStatement覆盖
Cluster.addPrepared
正在查看查询的某种MD5哈希,它用新的PreparedStatement覆盖旧的PreparedStatement
为了克服这种行为,我们创建了两个单独的查询(第二个查询与第一个查询相比在末尾有一个额外的空间)来区分它们,以便最终得到两个准备好的语句
例如:第一个查询:select*fromtest
,第二个查询:“select*fromtest”
是否有更好的方法为同一查询字符串创建两个单独的PreparedStatement,以满足用例的要求?在我们看来,它很容易出错
我们使用的是cassandra-drive-core-3.1.0-shaded.jar
import com.datastax.driver.core.*;
import com.datastax.driver.core.exceptions.NoHostAvailableException;
import com.datastax.driver.core.policies.DowngradingConsistencyRetryPolicy;
import com.datastax.driver.core.policies.LoggingRetryPolicy;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.stream.Stream;
public class CassandraHelper {
private static final Logger log = LoggerFactory.getLogger(CassandraHelper.class);
private final String hostname;
private final int port;
private Cluster cluster;
private Session session;
private static final String selectStackoverflowCql =
"SELECT key_part_one, key_part_two, data FROM test_keyspace.stackoverflow_composite WHERE key_part_one=? AND key_part_two=?";
private static final String selectStackoverflowCqlWithSpace =
"SELECT key_part_one, key_part_two, data FROM test_keyspace.stackoverflow_composite WHERE key_part_one=? AND key_part_two=? ";
private PreparedStatement selectStackoverflowWithoutRetryPolicyStatement;
private PreparedStatement selectStackoverflowStatement;
private PreparedStatement selectStackoverflowStatementWithSpace;
public CassandraHelper(String host, int port) {
this.hostname = host;
this.port = port;
connect();
install_schema();
selectStackoverflowStatement = session.prepare(selectStackoverflowCql)
.setRetryPolicy(new LoggingRetryPolicy(DowngradingConsistencyRetryPolicy.INSTANCE));
selectStackoverflowWithoutRetryPolicyStatement = session.prepare(selectStackoverflowCql);
selectStackoverflowStatementWithSpace = session.prepare(selectStackoverflowCqlWithSpace)
.setRetryPolicy(new LoggingRetryPolicy(DowngradingConsistencyRetryPolicy.INSTANCE));
}
public void connect() {
int maxRetries = 2;
for (int numReties = 0; numReties < maxRetries; numReties += 1) {
log.info("Connecting (attempt {})...", numReties);
try {
cluster = buildCluster();
session = cluster.connect();
log.info("Created session");
ResultSet rs = session.execute("select release_version from system.local");
Row row = rs.one();
log.info("Version: {}", row.getString("release_version"));
return;
} catch (NoHostAvailableException ex) { // if we get this exception, wait for Cassandra to become available
log.info("Got NoHostAvailableException");
}
}
throw new RuntimeException("Failed to connect to Cassandra cluster");
}
private Cluster buildCluster() {
if (this.cluster == null || this.cluster.isClosed()) {
this.cluster = Cluster.builder()
.withMaxSchemaAgreementWaitSeconds(20)
.addContactPointsWithPorts(Lists.newArrayList(new InetSocketAddress(this.hostname, this.port)))
.withoutJMXReporting().build();
this.cluster.init();
log.info("Built cluster");
cluster.getConfiguration().getQueryOptions().setDefaultIdempotence(true);
}
return cluster;
}
public PreparedStatement getSelectStackoverflowStatementWithSpace() {
return selectStackoverflowStatementWithSpace;
}
public PreparedStatement getSelectStackoverflowWithoutRetryPolicyStatement() {
return selectStackoverflowWithoutRetryPolicyStatement;
}
public PreparedStatement getSelectStackoverflowStatement() {
return selectStackoverflowStatement;
}
private void install_schema() {
List<String> creationCqls = Lists.newArrayList(
"CREATE KEYSPACE IF NOT EXISTS test_keyspace WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': 1 }",
"CREATE TABLE IF NOT EXISTS test_keyspace.stackoverflow_composite (key_part_one text, key_part_two int, data text, PRIMARY KEY(key_part_one, key_part_two))");
Stream<String> stream = creationCqls.stream();
stream.forEach(cql -> {
if (!executeSchemaChange(cql)) {
log.info("Schema agreement timeout attempting to execute {}. (This is not a problem as we will wait for schema agreement in the verification step.", cql);
}
});
}
public boolean executeSchemaChange(String cql) {
ResultSet rs = session.execute(cql);
return rs.getExecutionInfo().isSchemaInAgreement();
}
public static void main(String[] args) {
CassandraHelper ch = new CassandraHelper("localhost", 32769);
assert (ch.getSelectStackoverflowWithoutRetryPolicyStatement() == ch.getSelectStackoverflowStatement());
assert (ch.getSelectStackoverflowStatementWithSpace() != ch.getSelectStackoverflowStatement());
System.out.println("Statement without Retry Statement: " + ch.getSelectStackoverflowWithoutRetryPolicyStatement());
System.out.println("Statement with Retry and query not having space: " + ch.getSelectStackoverflowStatement());
System.out.println("Statement with Retry and query with space: " + ch.getSelectStackoverflowStatementWithSpace());
}
}
import com.datastax.driver.core.*;
导入com.datastax.driver.core.exceptions.NoHostAvailableException;
导入com.datastax.driver.core.policies.downggradingConsistencyRetryPolicy;
导入com.datastax.driver.core.policies.LoggingRetryPolicy;
导入com.google.common.collect.list;
导入org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
导入java.net.InetSocketAddress;
导入java.util.List;
导入java.util.stream.stream;
公共级卡桑德拉赫珀{
私有静态最终记录器log=LoggerFactory.getLogger(CassandraHelper.class);
私有最终字符串主机名;
私人最终国际港口;
私有集群;
非公开会议;
私有静态最终字符串selectStackoverflowCql=
“选择key_part_one,key_part_two,test_keyspace.stackoverflow_composite中的数据,其中key_part_one=?和key_part_two=?”;
私有静态最终字符串selectStackoverflowCqlWithSpace=
“选择key_part_one,key_part_two,test_keyspace.stackoverflow_composite中的数据,其中key_part_one=?和key_part_two=?”;
private PreparedStatement选择StackOverflowWithout RetryPolicyStatement;
私人编制的报表选择StackOverflows报表;
private Prepared Statement SelectStackOverflowsStatement with Space;
公共CassandraHelper(字符串主机,int端口){
this.hostname=host;
this.port=端口;
connect();
安装_schema();
选择StackOverflowStatement=session.prepare(选择StackOverflowCQL)
.setRetryPolicy(新的LoggingRetryPolicy(downggradingConsistencyRetryPolicy.INSTANCE));
选择StackOverflowWithOutRetryPolicyStatement=session.prepare(选择StackOverflowCQL);
选择StackOverflowStatementWithSpace=session.prepare(选择StackOverflowCqlWithSpace)
.setRetryPolicy(新的LoggingRetryPolicy(downggradingConsistencyRetryPolicy.INSTANCE));
}
公共void connect(){
int maxRetries=2;
对于(int numReties=0;numReties{
如果(!executeSchemaChange(cql)){
info(“尝试执行{}的架构协议超时(这不是问题,因为我们将在验证步骤中等待架构协议。”,cql);
}
});
}
公共布尔值executeSchemaChange(字符串cql){
ResultSet rs=会话.execute(cql);
返回rs.getExecutionInfo().isSchemaInAgreement();
}
公共静态void main(字符串[]args){
CassandraHelper ch=新的CassandraHelper(“本地主机”,32769);
assert(ch.getSelectStackoverflowWithoutRetryPolicyStatement()==