cassandra-driver-core:将列表值传递给参数化的SimpleStatement

时间:2014-09-12 10:07:12

标签: java cassandra cql3

我目前正在使用官方数据驱动程序驱动程序(V2.0)编写一个非常基本的CQL访问层,并在将参数值传递给语句时苦苦挣扎。

这是一个例子

列系列(简化)

USE myKeyspace;

CREATE TABLE MyTable (
    myId timeuuid,
    myTypeId int,
    myVal varchar,
    PRIMARY_KEY( myId, myTypeId )
);

CREATE INDEX MyTable_myTypeID 
    ON MyTable( myTypeId );

基本思想是存储一些具有多个值的事件数据(每个"事件"),这就是我使用组合PK的原因。每个事件都有基于时间的UUID,每个typeId可能有多个条目。 从建模的角度来看,这是否有意义?

我现在要做的只是获取一个选择' typeIds'的事件的条目。

public void myQueryCode() {

    Cluster.Builder builder = Cluster.builder();
    builder.withPort( 9142 );
    builder.addContactPoints( "127.0.0.1" );
    cluster = builder.build();
    Session session = cluster.connect( "myKeyspace" );

    List<Integer> typeFilter = new ArrayList<> ();
    typeFilter.add( 1 );
    typeFilter.add( 2 );

    Statement stmt = new SimpleStatement( 
        "SELECT * FROM MyTable where myId = ?" +
        " AND myTypeId IN (?,?)" +
        " ALLOW FILTERING",
        UUID.randomUUID(),
        typeFilter );

    ResultSet result = session.execute( stmt );

    // do something with results
}

但是,我只是在声明的值序列化中深入了解异常。

com.datastax.driver.core.exceptions.InvalidQueryException: Expected 4 or 0 byte int (8)
at com.datastax.driver.core.exceptions.InvalidQueryException.copy(InvalidQueryException.java:35)
at com.datastax.driver.core.DefaultResultSetFuture.extractCauseFromExecutionException(DefaultResultSetFuture.java:256)
at com.datastax.driver.core.DefaultResultSetFuture.getUninterruptibly(DefaultResultSetFuture.java:172)
at com.datastax.driver.core.AbstractSession.execute(AbstractSession.java:52)

我不确定将列表作为第二个参数传递,驱动程序是否正在获取参数,但是这可能仅适用于集合类型列上的插入?

2 个答案:

答案 0 :(得分:2)

您正在传递的List被强制插入第二个参数,这是正确的,这会导致InvalidQueryException。

Statement stmt = new SimpleStatement( 
        "SELECT * FROM MyTable where myId = ?#1" +
        " AND myTypeId IN (?#2,?#3)" +
        " ALLOW FILTERING",
        #1 UUID.randomUUID(),
        #2 typeFilter );

由于typeFilter是一个列表,因此驱动程序会尝试将List Collection对象放入参数2中,并且事情变得很糟糕。这是因为当您运行此类语句(未准备好)时,驱动程序无法检查类型Comment in code。相反,如果您传入

Statement stmt = new SimpleStatement( 
            "SELECT * FROM MyTable where myId = ?#1" +
            " AND myTypeId IN (?#2,?#3)" +
            " ALLOW FILTERING",
            #1 UUID.randomUUID(),
            #2 typeFilter.get(0)
            #3 typeFilter.get(1));

你会没事的。或者,如果您已经准备好了语句,那么您将收到编译时错误警告。

答案 1 :(得分:1)

在回答您的第一个问题时,从建模的角度来看,存储“一些具有多个值的事件数据(每个”事件“)是否有意义,这就是我使用组合PK的原因。每个事件都有其时间 - 基于UUID,每个typeId可能有多个条目,“是绝对的。这与Cassandra团队在音乐服务的数据建模示例中使用的场景类似:http://www.datastax.com/documentation/cql/3.1/cql/ddl/ddl_music_service_c.html

在代码中查找一个小错误,因为我可以在命令行上执行您的示例:

CREATE TABLE MyTable (
    myId timeuuid,
    myTypeId int,
    myVal varchar,
    PRIMARY_KEY( myId, myTypeId )
);
CREATE INDEX MyTable_myTypeID 
    ON MyTable( myTypeId );
insert into mytable( myid, mytypeid, myval) VALUES (d2177dd0-eaa2-11de-a572-001b779c76e3, 100, 'somechar')
insert into mytable( myid, mytypeid, myval) VALUES (d2177dd0-eaa2-11de-a572-001b779c76e3, 200, 'anotherchar')
SELECT * FROM MyTable where myId = d2177dd0-eaa2-11de-a572-001b779c76e3 AND myTypeId IN (100,200) ALLOW FILTERING;

输出是:

myid                                 | mytypeid | myval
--------------------------------------+----------+-------------
 d2177dd0-eaa2-11de-a572-001b779c76e3 |      100 |    somechar
 d2177dd0-eaa2-11de-a572-001b779c76e3 |      200 | anotherchar