问题
I am tyring to insert into Composite Column in Cassandra column family using Astyanax client. Below is my column family in Cassandra.
create column family USER_DATA
with key_validation_class = 'UTF8Type'
and comparator = 'CompositeType(UTF8Type,UTF8Type,DateType)'
and default_validation_class = 'UTF8Type'
and gc_grace = 86400;
I am expecting after insertion, it will look like this
user-id column1
123 (Column1-Value Column1-SchemaName LastModifiedDate)
Below is my java main code-
public static void main(String[] args) {
ComplexType ct = new ComplexType();
ct.setVal1("Hello");
ct.setVal2("World");
ct.setTimestamp(System.currentTimeMillis());
// e1 is the column-name and ct is its composite-value.
attributesMap.put("e1", ct);
clientDao.upsertCompositeAttributes("123", attributesMap, "USER_DATA");
}
Below is my ComplexType class-
public static class ComplexType {
@Component(ordinal = 0)
String val1;
@Component(ordinal = 1)
String val2;
@Component(ordinal = 2)
long timestamp;
public String getVal1() {
return val1;
}
public void setVal1(String val1) {
this.val1 = val1;
}
public String getVal2() {
return val2;
}
public void setVal2(String val2) {
this.val2 = val2;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
}
Below is my upsertCompositeAttributes
method in my DAOImpl class
.
public void upsertCompositeAttributes(final String rowKey, final Map<String, ComplexType> ct, final String columnFamilyName) {
try {
AnnotatedCompositeSerializer<ComplexType> complexTypeSerializer = new AnnotatedCompositeSerializer<ComplexType>(ComplexType.class);
ColumnFamily columnFamily = new ColumnFamily(columnFamilyName, StringSerializer.get(), StringSerializer.get());
MutationBatch m = CassandraAstyanaxConnection.getInstance().getKeyspace().prepareMutationBatch();
ColumnListMutation<String> mutation = m.withRow(columnFamily, rowKey);
for (Map.Entry<String, ComplexType> entry : ct.entrySet()) {
// entry.getKey() is the column name and entry.getValue() is its composite value.
mutation = mutation.putColumn(entry.getKey(), entry.getValue(), complexTypeSerializer, null);
}
m.setConsistencyLevel(ConsistencyLevel.CL_ONE).execute();
} catch (ConnectionException e) {
} catch (Exception e) {
}
}
Now I am getting the below exception-
com.netflix.astyanax.connectionpool.exceptions.BadRequestException: BadRequestException: [host=10.109.107.27(10.109.107.27):9160, latency=99(131), attempts=1]InvalidRequestException(why:Not enough bytes to read value of component 0)
at com.netflix.astyanax.thrift.ThriftConverter.ToConnectionPoolException(ThriftConverter.java:159)
at com.netflix.astyanax.thrift.AbstractOperationImpl.execute(AbstractOperationImpl.java:65)
at com.netflix.astyanax.thrift.AbstractOperationImpl.execute(AbstractOperationImpl.java:28)
at com.netflix.astyanax.thrift.ThriftSyncConnectionFactoryImpl$ThriftConnection.execute(ThriftSyncConnectionFactoryImpl.java:151)
at com.netflix.astyanax.connectionpool.impl.AbstractExecuteWithFailoverImpl.tryOperation(AbstractExecuteWithFailoverImpl.java:69)
at com.netflix.astyanax.connectionpool.impl.AbstractHostPartitionConnectionPool.executeWithFailover(AbstractHostPartitionConnectionPool.java:256)
at com.netflix.astyanax.thrift.ThriftKeyspaceImpl.executeOperation(ThriftKeyspaceImpl.java:485)
at com.netflix.astyanax.thrift.ThriftKeyspaceImpl.access$000(ThriftKeyspaceImpl.java:79)
at com.netflix.astyanax.thrift.ThriftKeyspaceImpl$1.execute(ThriftKeyspaceImpl.java:123)
at com.cassandra.astyanax.CassandraAstyanaxClient.upsertCompositeAttributes(CassandraAstyanaxClient.java:167)
at com.example.AstyanaxCompositeColumns.main(AstyanaxCompositeColumns.java:24)
Caused by: InvalidRequestException(why:Not enough bytes to read value of component 0)
at org.apache.cassandra.thrift.Cassandra$batch_mutate_result.read(Cassandra.java:20833)
at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:78)
at org.apache.cassandra.thrift.Cassandra$Client.recv_batch_mutate(Cassandra.java:964)
at org.apache.cassandra.thrift.Cassandra$Client.batch_mutate(Cassandra.java:950)
at com.netflix.astyanax.thrift.ThriftKeyspaceImpl$1$1.internalExecute(ThriftKeyspaceImpl.java:129)
at com.netflix.astyanax.thrift.ThriftKeyspaceImpl$1$1.internalExecute(ThriftKeyspaceImpl.java:126)
at com.netflix.astyanax.thrift.AbstractOperationImpl.execute(AbstractOperationImpl.java:60)
... 9 more
Below is my CassandraAstyanaxConnection class-
private CassandraAstyanaxConnection() {
context = new AstyanaxContext.Builder()
.forCluster(Constants.CLUSTER)
.forKeyspace(Constants.KEYSPACE)
.withConnectionPoolConfiguration(new ConnectionPoolConfigurationImpl("MyConnectionPool")
.setPort(9160)
.setMaxConnsPerHost(1000)
.setSeeds("host:9160")
)
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
.setCqlVersion("3.0.0")
.setTargetCassandraVersion("1.2")
.setConnectionPoolType(ConnectionPoolType.ROUND_ROBIN)
.setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE))
.withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
.buildKeyspace(ThriftFamilyFactory.getInstance());
context.start();
keyspace = context.getEntity();
emp_cf = ColumnFamily.newColumnFamily(
Constants.COLUMN_FAMILY,
StringSerializer.get(),
StringSerializer.get());
}
First of all, my column family is correct or not?
create column family USER_DATA
with key_validation_class = 'UTF8Type'
and comparator = 'CompositeType(UTF8Type,UTF8Type,DateType)'
and default_validation_class = 'UTF8Type'
and gc_grace = 86400;
Below is my requirement per our use case-
user-id column1 column2 column3
123 (Column1-Value Column1-SchemaName LMD) (Column2-Value Column2-SchemaName LMD) (Column3-Value Column3-SchemaName LMD)
For each user-id, we will be storing column1 and its value and that value will store these three things always-
(Column1-Value Column1-SchemaName LMD)
In my above example, I have show only three columns but it might have more columns.
I am running Cassandra 1.2.9
回答1:
When you create the ColumnFamily, the arguments are for the columnName, the rowKey serializer and the column name serializer. The column type serializer (complexTypeSerializer) is only used in the putColumn. You should have:
ColumnFamily columnFamily = new ColumnFamily(columnFamilyName, StringSerializer.get(), StringSerializer.get());
since you are not using composite column names but composite column values.
来源:https://stackoverflow.com/questions/18906147/not-enough-bytes-to-read-value-of-component-using-composite-columns-with-astyana