简体   繁体   English

如何在Cassandra中使用datastax java驱动程序有效地使用准备好的语句?

[英]How to use prepared statement efficiently using datastax java driver in Cassandra?

I need to query one of the tables in Cassandra using Datastax Java driver.我需要使用 Datastax Java 驱动程序查询 Cassandra 中的表之一。 Below is the code I have which works fine -下面是我工作正常的代码 -

public class TestCassandra {

        private Session session = null;
        private Cluster cluster = null;

        private static class ConnectionHolder {
            static final TestCassandra connection = new TestCassandra();
        }

        public static TestCassandra getInstance() {
            return ConnectionHolder.connection;
        }

        private TestCassandra() {
            Builder builder = Cluster.builder();
            builder.addContactPoints("127.0.0.1");

            PoolingOptions opts = new PoolingOptions();
            opts.setCoreConnectionsPerHost(HostDistance.LOCAL, opts.getCoreConnectionsPerHost(HostDistance.LOCAL));

            cluster = builder.withRetryPolicy(DowngradingConsistencyRetryPolicy.INSTANCE).withPoolingOptions(opts)
                    .withLoadBalancingPolicy(new TokenAwarePolicy(new DCAwareRoundRobinPolicy("DC2")))
                    .withReconnectionPolicy(new ConstantReconnectionPolicy(100L))
                    .build();
            session = cluster.connect();
        }

    private Set<String> getRandomUsers() {
        Set<String> userList = new HashSet<String>();

        for (int table = 0; table < 14; table++) {
            String sql = "select * from testkeyspace.test_table_" + table + ";";

            try {
                SimpleStatement query = new SimpleStatement(sql);
                query.setConsistencyLevel(ConsistencyLevel.QUORUM);
                ResultSet res = session.execute(query);

                Iterator<Row> rows = res.iterator();
                while (rows.hasNext()) {
                    Row r = rows.next();

                    String user_id = r.getString("user_id");
                    userList.add(user_id);
                }
            } catch (Exception e) {
                System.out.println("error= " + ExceptionUtils.getStackTrace(e));
            }
        }

        return userList;
    }
}

I am using above class like this in my main application -我在我的主应用程序中像这样使用上面的类 -

TestCassandra.getInstance().getRandomUsers();

Is there any way I can use PreparedStatement in getRandomUsers efficiently?有什么方法可以有效地在getRandomUsers使用PreparedStatement吗? I guess I need to make sure that I am creating PreparedStatement only once instead of creating it multiple times.我想我需要确保我只创建PreparedStatement一次,而不是创建多次。 What is the best design for that in my current architecture and how can I use it?在我当前的架构中,最好的设计是什么,我该如何使用它?

You can create a cache (this is a fairly basic example to give you an idea) of the statements you need.您可以创建所需语句的缓存(这是一个相当基本的示例,可以让您了解)。 Lets start by creating the class that will be used as a cache.让我们从创建将用作缓存的类开始。

private class StatementCache {
    Map<String, PreparedStatement> statementCache = new HashMap<>();
    public BoundStatement getStatement(String cql) {
        PreparedStatement ps = statementCache.get(cql);
        // no statement cached, create one and cache it now.
        if (ps == null) {
            ps = session.prepare(cql);
            statementCache.put(cql, ps);
        }
        return ps.bind();
    }
}

Then add an instance to your singleton:然后将一个实例添加到您的单例中:

public class TestCassandra {
    private Session session = null;
    private Cluster cluster = null;
    private StatementCache psCache = new StatementCache();
    // rest of class...

And finally use the cache from your function:最后使用函数中的缓存:

private Set<String> getRandomUsers(String cql) {
// lots of code.    
        try {
            SimpleStatement query = new SimpleStatement(cql);
            query.setConsistencyLevel(ConsistencyLevel.QUORUM);
            // abstract the handling of the cache to it's own class.
            // this will need some work to make sure it's thread safe
            // as currently it's not.
            ResultSet res = session.execute(psCache.getStatement(cql));

My implementation is more or less the same as the ones shared above, but with performance checks and implementations to take care of race conditions.See inline comments on code on my thought process.我的实现或多或少与上面共享的相同,但有性能检查和实现来处理竞争条件。请参阅我思考过程中代码的内联注释。

 import com.datastax.driver.core.PreparedStatement;
 import com.datastax.driver.core.Session;
 import nl.ing.creditcards.commons.activity.ActivityException;

 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;

public class StatementCache {

/* prevent cache incoherence issues*/
private static volatile StatementCache sCacheInstance;
private static final Map<String, PreparedStatement> holder = new ConcurrentHashMap<>();
private static final String NOT_PERMITTED = "Operation not permitted";

private StatementCache() {
    /*Prevent access through reflection api.*/
    if (sCacheInstance != null) {
        throw new ActivityException(NOT_PERMITTED, "Use getInstance() to retrieve the instance of this class");
    }
}

/**
 * Double check locking pattern usage for singleton classes
 *
 * @return
 */
public static StatementCache getInstance() {
    if (sCacheInstance == null) { //Check for the first time
        synchronized (StatementCache.class) { // second check in order to keep the operation atomic
            if (sCacheInstance == null) sCacheInstance = new StatementCache();
        }
    }
    return sCacheInstance;
}

/**
 * If {@link StatementCache#getStatement#prepared_statement} is already present in cache,
 * then we don't have to synchronize and make threads wait, otherwise, we synchronize the caching bit.
 *
 * @param session
 * @param cql
 * @return
 */
public PreparedStatement getStatement(Session session, String cql) {
    PreparedStatement prepared_statement = holder.get(cql);
    if (prepared_statement == null) {
        synchronized (this) {
            prepared_statement = holder.get(cql);
            if (prepared_statement == null) {
                prepared_statement = session.prepare(cql);
                holder.put(cql, prepared_statement);
            }
        }
    }
    return prepared_statement;
  }
}

Using this cache singleton class would be as simple as :使用这个缓存单例类将非常简单:

public class CacheConsumer{

    private static Session session;

    CacheConsumer(Session session){
     this.session=session;
   }

    public void someMethod(){
      String cqlstatement = "SELECT * FROM SOME_TABLE";
      PreparedStatement statement= 
       StatementCache.getInstance().getStatement(session,cqlstatement);
         // You can now use the prepared statement however you wish.
   }
}

Pretty simple ;)很简单;)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用datastax java驱动程序有效地使用批量写入cassandra? - How to efficiently use Batch writes to cassandra using datastax java driver? 带分页的Datastax Cassandra Java驱动程序RetryPolicy - Datastax Cassandra java driver RetryPolicy for Statement with paging 如何使用带有Datastax Java驱动程序的CQL向Cassandra添加任意列? - How to add arbitrary columns to Cassandra using CQL with Datastax Java driver? 无法使用Cassandra Datastax Java驱动程序连接到Cassandra节点之一 - Unable to connect to one of the Cassandra nodes using Cassandra Datastax Java Driver Datastax Java Cassandra驱动程序:使用WHERE的多个AND语句? - Datastax Java Cassandra Driver: Multiple AND statements using WHERE? Cassandra:使用 DataStax Java 驱动程序选择一系列 TimeUUID - Cassandra: Selecting a Range of TimeUUIDs using the DataStax Java Driver 使用DataStax Java驱动程序1.0.4使用CQL连接到Cassandra时出现异常 - Exception when connecting to Cassandra with CQL using DataStax Java driver 1.0.4 我应该如何使用java的datastax cassandra驱动程序检查resultset是空还是null - How should I check if resultset is empty or null using datastax cassandra driver for java 如何使用Datastax Java驱动程序在属性文件中提供Cassandra的连接详细信息 - How to give connection details for cassandra in properties file using datastax java driver Cassandra Java driver @Select注解是否使用Prepared Statements? - Does the Cassandra Java driver @Select annotation use Prepared Statements?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM