Java Cassandra Datastax 驱动程序自定义编解码器不处理集合类型
Java Cassandra Datastax driver custom codec not handling collection types
我以教程为参考定义了一个自定义编解码器- 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;
}
}
基本上,在序列化方法中,我试图提取一个 userId 字符串(使用 user.getUserId()),然后将其作为 userid 字符串存储在我的 cassandra table 中。在反序列化中,我只是将给定的 ByteBuffer 实例转换为字符串并 return 它。
这在序列化时非常适用于字符串、集合和列表(即,如果我有一个集合,编解码器对集合的每个单独元素执行 serialize() 并将相应的字符串存储在我的 casandra table 中)。但是,在反序列化 cassandra 中的集合字段期间,反序列化方法将整个集合发送到 ByteBuffer 对象中。通过分析 ByteBuffer 对象,我可以看到各个元素都在那里。请注意,反序列化是在集合的每个元素上执行的。因此,如果集合有 5 个元素,反序列化将执行 5 次,但每次都不会发送 ByteBuffer 中的特定元素,而是发送整个集合。
所以,我不明白为什么会这样,而且 google 没有太大帮助。任何 suggestions/solutions 都非常受欢迎,因为我已经坚持了很长时间了。
谢谢!
AbstractCollectionCodec
是 SetCodec
和 ListCodec
用于 serialize/deserialize 集合的。在反序列化时,它们将位于元素开始位置 (ByteBuffer.position()
) 并受单个元素结尾 (ByteBuffer.limit()
) 限制的整个 ByteBuffer
传递给底层元素编解码器(在此案例,UserCodec
)。
当您调用 buffer.array()
时,您将获得 ByteBuffer
的整个支持数组,而不管位置或限制。
对您来说更好的方法是使用 Bytes.getArray(ByteBuffer)
,其中 returns 您是 limit
和 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;
}
因为您只是将 User
实例作为表示其 getUserId()
的字符串存储在 C* 中,您可以做的是从 extras 模块创建 MappingCodec
的实例简单地映射 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();
}
}
您可以阅读更多关于 MappingCodec
on the docs site。
我以教程为参考定义了一个自定义编解码器- 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;
}
}
基本上,在序列化方法中,我试图提取一个 userId 字符串(使用 user.getUserId()),然后将其作为 userid 字符串存储在我的 cassandra table 中。在反序列化中,我只是将给定的 ByteBuffer 实例转换为字符串并 return 它。 这在序列化时非常适用于字符串、集合和列表(即,如果我有一个集合,编解码器对集合的每个单独元素执行 serialize() 并将相应的字符串存储在我的 casandra table 中)。但是,在反序列化 cassandra 中的集合字段期间,反序列化方法将整个集合发送到 ByteBuffer 对象中。通过分析 ByteBuffer 对象,我可以看到各个元素都在那里。请注意,反序列化是在集合的每个元素上执行的。因此,如果集合有 5 个元素,反序列化将执行 5 次,但每次都不会发送 ByteBuffer 中的特定元素,而是发送整个集合。 所以,我不明白为什么会这样,而且 google 没有太大帮助。任何 suggestions/solutions 都非常受欢迎,因为我已经坚持了很长时间了。
谢谢!
AbstractCollectionCodec
是 SetCodec
和 ListCodec
用于 serialize/deserialize 集合的。在反序列化时,它们将位于元素开始位置 (ByteBuffer.position()
) 并受单个元素结尾 (ByteBuffer.limit()
) 限制的整个 ByteBuffer
传递给底层元素编解码器(在此案例,UserCodec
)。
当您调用 buffer.array()
时,您将获得 ByteBuffer
的整个支持数组,而不管位置或限制。
对您来说更好的方法是使用 Bytes.getArray(ByteBuffer)
,其中 returns 您是 limit
和 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;
}
因为您只是将 User
实例作为表示其 getUserId()
的字符串存储在 C* 中,您可以做的是从 extras 模块创建 MappingCodec
的实例简单地映射 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();
}
}
您可以阅读更多关于 MappingCodec
on the docs site。