使用JDBC驱动程序将UUID插入到Cassandra 1.2时出错

问题描述:

尝试使用JDBC驱动程序将UUID插入Cassandra 1.2时出现异常。下面的代码:使用JDBC驱动程序将UUID插入到Cassandra 1.2时出错

UUID uuid = java.util.UUID.randomUUID(); 
PreparedStatement statement = c.prepareStatement("insert into tree (tree_id) values (?)"); 
statement.setObject(1, uuid); 
statement.execute(); 

这里是例外,我得到:

java.sql.SQLNonTransientException: encountered object of class: class java.util.UUID, but only 'String' is supported to map to the various VARCHAR types 
     at org.apache.cassandra.cql.jdbc.HandleObjects.makeBadMapping(HandleObjects.java:124) 
     at org.apache.cassandra.cql.jdbc.HandleObjects.makeBytes(HandleObjects.java:391) 
     at org.apache.cassandra.cql.jdbc.CassandraPreparedStatement.setObject(CassandraPreparedStatement.java:351) 
     at org.apache.cassandra.cql.jdbc.CassandraPreparedStatement.setObject(CassandraPreparedStatement.java:338) 
     at CassandraTest.main(CassandraTest.java:26) 

,这里是我的架构:

CREATE TABLE browse.tree (tree_id UUID PRIMARY KEY, activation_time TIMESTAMP, tree_lock_id INT, sql_publication_id INT); 

怪异的类,它认为我的UUID字段是VARCHAR。任何帮助将不胜感激。谢谢!

UUID不是java.sql.Types规范的一部分。我的读法是,正确的行为是驱动程序抛出一个SQLException。或者,它可以弯曲一些规则并接受它。

作为解决方法,uuid的字符串表示法应该可以工作,但我真的推荐使用native CQL driver而不是JDBC。您不会遇到任何这些规格不匹配,并且在处理故障转移和负载平衡等方面做得更好。

+0

谢谢,但字符串表示也不起作用。说它需要是正好16个字节。 Byte []不起作用(与UUID相同的错误)。 UUID是最重要的类型之一,我很难看到如何完全打破。我会研究本地的CQL驱动程序。 – 2013-05-02 03:25:04

+0

正如Jonathan所说,尝试使用原生CQL驱动程序。进一步为了生成UUID值,请参阅cassandra FAQ,如何生成UUID,这里给出了一个很好的描述 – abhi 2013-05-02 05:57:01

您可以使用模式自省来解决此限制。

我的表:

CREATE TABLE TEST_KEY(PK UUID,文本VARCHAR,主键(PK));

我反省:

package org.apache.cassandra.cql.jdbc; 

import java.sql.PreparedStatement; 
import java.sql.SQLException; 
import java.sql.Types; 
import java.util.UUID; 


public class CassandraPS { 

    private PreparedStatement ps; 

    public CassandraPS(PreparedStatement ps) { 
     this.ps = ps; 
    } 

    public void setUUID(int parameterIndex, UUID uuid) throws SQLException { 
     CassandraPreparedStatement psCas = (CassandraPreparedStatement) ps; 
     psCas.setObject(parameterIndex, JdbcUUID.instance.decompose(uuid).array(), 
     Types.LONGVARBINARY); 
    } 
} 

吾道:

....... DAO .......... 
public void insert(UUID pk, String text) throws SQLException { 
    String cql = "insert into my_ks.test_key(pk, text) values(?,?)"; 
    PreparedStatement ps = null; 
    try { 
     ps = conn.prepareStatement(cql); 
     new CassandraPS(ps).setUUID(1, pk); 
     ps.setString(2, text); 
     ps.executeUpdate(); 
    } finally { 
     if (ps != null) { 
     ps.close(); 
    } 
    } 
} 
... 

我的司机: 卡桑德拉-JDBC-1.2.5.jar

吉尔伯托·维埃拉·达席尔瓦

吉尔伯托是对的。使用此功能可按:

public static byte[] uuid2ByteArray(java.util.UUID uuid) { 
    long msb = uuid.getMostSignificantBits(); 
    long lsb = uuid.getLeastSignificantBits(); 
    byte[] buffer = new byte[16]; 

    for (int i = 0; i < 8; i++) { 
     buffer[i] = (byte) (msb >>> 8 * (7 - i)); 
    } 
    for (int i = 8; i < 16; i++) { 
     buffer[i] = (byte) (lsb >>> 8 * (7 - i)); 
    } 

    return buffer; 
} 

转换的UUID的字节数组,然后ps.setObject(索引,BYTE_ARRAY,Types.VARBINARY)也适用