Java Cassandra Datastax驱动程序自定义编解码器不处理集合类型

时间:2016-03-20 03:49:41

标签: datastax-java-driver cassandra-2.1

我已经定义了一个自定义编解码器,将教程作为参考 - https://docs.datastax.com/en/latest-java-driver/java-driver/reference/customCodecs.html。这是我的编解码器要求: -

    package org.questqa.server.database.codecs;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;

import org.questqa.server.database.fetchers.UserInfoFetcher;
import org.questqa.server.entity.User;
import org.springframework.beans.factory.annotation.Autowired;

import com.datastax.driver.core.DataType;
import com.datastax.driver.core.ProtocolVersion;
import com.datastax.driver.core.TypeCodec;
import com.datastax.driver.core.exceptions.InvalidTypeException;

public class UserCodec extends TypeCodec<User>
{

    @Autowired
    UserInfoFetcher userFetcher;

    public UserCodec(DataType cqlType, Class<User> javaClass) 
    {
        super(cqlType, javaClass);
    }

    @Override
    public User deserialize(ByteBuffer buffer, ProtocolVersion arg1) `throws InvalidTypeException {`
        // TODO Auto-generated method stub
        System.out.println("Executing deserialize");
        User user = new User();
        try {
            System.out.println("Size of ByteBuffer: " + `buffer.array().length);`
            String userId = new String(buffer.array(), "UTF-8");
            System.out.println("User id to set: " + userId);
            System.out.println("Setting user id...");
            user.setUserId(userId);
            System.out.println("User id set: " + user.getUserId());
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return user;
    }
    @Override
    public String format(User user) throws InvalidTypeException 
    {
        System.out.println("Executing format");
        return user.getUserId();
    }
    @Override
    public User parse(String userId) throws InvalidTypeException 
    {
        // TODO Auto-generated method stub
        System.out.println("Executing parse");
        User user = new User();
        user.setUserId(userId);
        return user;
    }
    @Override
    public ByteBuffer serialize(User user, ProtocolVersion arg1) throws `InvalidTypeException {`
        // TODO Auto-generated method stub
        System.out.println("Executing serialize");
        ByteBuffer buffer = null;
        System.out.println("Userid to serialize: " + user.getUserId());
        try {
            buffer = ByteBuffer.wrap(user.getUserId().getBytes("UTF-8"));
            String bufferStr = new String(buffer.array(), "UTF-8");
            System.out.println("ByteBuffer to be returned: \nLength: " + `buffer.array().length +` 
                    "\nValue: " + bufferStr);
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return buffer;
    }
}

基本上,在serialize方法中,我正在尝试提取userId字符串(使用user.getUserId()),然后将其作为用户ID字符串存储在我的cassandra表中。在反序列化中,我只是将给定的ByteBuffer实例转换为字符串并返回它。 这在序列化时对字符串,集合和列表完全正常(即,如果我有一个Set,则编解码器对集合的每个单独元素执行serialize()并将相应的字符串存储在我的casandra表中)。但是,在对cassandra中的set字段进行反序列化时,deserialize方法会在ByteBuffer对象中发送整个集合。通过分析ByteBuffer对象,我可以看到各个元素都在那里。请注意,对集合的每个元素执行反序列化。因此,如果集合有5个元素,则反序列化执行5次,但每次,而不是发送ByteBuffer中的特定元素,它会发送整个集合。 所以,我不明白为什么这样做,谷歌没有太大的帮助。任何建议/解决方案都是最受欢迎的,因为我已经坚持了很长一段时间。

谢谢!

1 个答案:

答案 0 :(得分:2)

AbstractCollectionCodecSetCodecListCodec用于序列化/反序列化集合的内容。在反序列化时,它们传递位于元素开始位置的整个ByteBufferByteBuffer.position()),并将单个元素(ByteBuffer.limit())的末尾限制为基础元素编解码器(在此情况1}})。

当您致电UserCodec时,您将获得buffer.array()的整个支持数组,无论其位置或限制如何。

对你来说更好的方法是使用Bytes.getArray(ByteBuffer)ByteBufferlimit之间的数据返回一个字节数组,即:

position

由于您只是将@Override public User deserialize(ByteBuffer buffer, ProtocolVersion arg1) `throws InvalidTypeException {` // TODO Auto-generated method stub System.out.println("Executing deserialize"); User user = new User(); try { byte[] data = Bytes.toArray(buffer); System.out.println("Size of ByteBuffer: " + data.length); String userId = new String(data, "UTF-8"); System.out.println("User id to set: " + userId); System.out.println("Setting user id..."); user.setUserId(userId); System.out.println("User id set: " + user.getUserId()); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return user; } 实例存储在C *中作为表示其User的字符串,您可以做的是从extras模块创建一个MappingCodec的实例,映射getUserId(),即:

User <-> String (UserId)

您可以详细了解import com.datastax.driver.core.TypeCodec; import com.datastax.driver.extras.codecs.MappingCodec; public class UserCodec extends MappingCodec<User, String> { public UserCodec() { super(TypeCodec.varchar(), User.class); } @Override protected User deserialize(String userId) { return new User(userId); } @Override protected String serialize(User user) { return user.getUserId(); } } on the docs site