Spring data Cassandra 2.0. Select a BLOB column that returns invalid ByteBuffer data.

Context: Spring data cassandra official 1.0.2.RELEASE from Maven Central repo, CQL3, cassandra 2.0, datastax 2.0.4 driver

Reference Information. The blob cabsrand data type maps to Java ByteBuffer.

The code example below shows that you will not receive the correct bytes using select next to the equivalent insert. In fact, the data received is prefixed with a lot of garbage bytes, which actually look like serialization of the entire string. This older post related to Cassandra 1.2 suggested that we might have to start with ByteBuffer.arrayOffset () of length ByteBuffer.remaining (), but the value of arrayOffset is actually 0.

I discovered spring-data-cassandra 2.0.0. SNAPSHOT, but the CassandraOperations API is very different, as well as its package name: org.springdata ... versus org.springframework ...

Help fix this, but we will be very happy.

At the same time, it looks like I need to encode / decode Base64 base data to / from a text data type column.

--- here is a simple CQL metadata table that I use -------------

CREATE TABLE person ( id text, age int, name text, pict blob, PRIMARY KEY (id) ) ; 

--- A simple data object follows, mapped to a CQL table ---

 package org.spring.cassandra.example; import java.nio.ByteBuffer; import org.springframework.data.cassandra.mapping.PrimaryKey; import org.springframework.data.cassandra.mapping.Table; @Table public class Person { @PrimaryKey private String id; private int age; private String name; private ByteBuffer pict; public Person(String id, int age, String name, ByteBuffer pict) { this.id = id; this.name = name; this.age = age; this.pict = pict; } public String getId() { return id; } public String getName() { return name; } public int getAge() { return age; } public ByteBuffer getPict() { return pict; } } } 

--- and simple Java application code that simply inserts and fetches a person object -

 package org.spring.cassandra.example; import java.nio.ByteBuffer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.data.cassandra.core.CassandraOperations; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import com.datastax.driver.core.querybuilder.QueryBuilder; import com.datastax.driver.core.querybuilder.Select; public class CassandraApp { private static final Logger logger = LoggerFactory .getLogger(CassandraApp.class); public static String hexDump(ByteBuffer bb) { char[] hexArray = "0123456789ABCDEF".toCharArray(); bb.rewind(); char[] hexChars = new char[bb.limit() * 2]; for ( int j = 0; j < bb.limit(); j++ ) { int v = bb.get() & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } bb.rewind(); return new String(hexChars); } public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("app-context.xml"); try { CassandraOperations cassandraOps = applicationContext.getBean( "cassandraTemplate", CassandraOperations.class); cassandraOps.truncate("person"); // prepare data byte[] ba = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x22, 0x33, 0x44, 0x55, (byte) 0xAA, (byte) 0xCC, (byte) 0xFF }; ByteBuffer myPict = ByteBuffer.wrap(ba); String myId = "1234567890"; String myName = "mickey"; int myAge = 50; logger.info("We try id=" + myId + ", name=" + myName + ", age=" + myAge +", pict=" + hexDump(myPict)); cassandraOps.insert(new Person(myId, myAge, myName, myPict )); Select s = QueryBuilder.select("id","name","age","pict").from("person"); s.where(QueryBuilder.eq("id", myId)); ResultSet rs = cassandraOps.query(s); Row r = rs.one(); logger.info("We got id=" + r.getString(0) + ", name=" + r.getString(1) + ", age=" + r.getInt(2) +", pict=" + hexDump(r.getBytes(3))); } catch (Exception e) { e.printStackTrace(); } } } 

--- assuming you set up a simple Spring project for cassandra as described in http://projects.spring.io/spring-data-cassandra/

Actual execution yields (shift these log traces to see the end):

[main] INFO org.spring.cassandra.example.CassandraApp - We try id = 1234567890, name = mickey, age = 50, pict = 0001020304051122334455AACCFF

[main] INFO org.spring.cassandra.example.CassandraApp - We got ID = 1234567890 name = Mickey, age = 50, pict = 8200000800000073000000020000000100000004000A6D796B657973706163650006706572736F6E00026964000D00046E616D65000D000361676500090004706963740003000000010000000A31323334353637383930000000066D69636B657900000004000000320000000E 0001020304051122334455AACCFF

although the insert looks right in the database itself, as seen from the cqlsh command line:

 cqlsh:mykeyspace> select * from person; id | age | name | pict ------------+-----+--------+-------------------------------- 1234567890 | 50 | mickey | 0x0001020304051122334455aaccff (1 rows) 
+6
source share
2 answers

I had exactly the same problem, but fortunately I found a solution. The problem is that using ByteBuffer is confusing. Try to do something like:

 ByteBuffer bb = resultSet.one().getBytes("column_name"); byte[] data = new byte[bb.remaining()]; bb.get(data); 

Thanks to Sylvain for this suggestion here: http://grokbase.com/t/cassandra/user/134brvqzd3/blobs-in-cql

+5
source

Look at the Bytes Java Datastax Driver class, it provides what you need to encode / decode your data.

In this post I wrote a usage example.

NTN, Carlo

+4
source

Source: https://habr.com/ru/post/973960/


All Articles