2016-03-20 6 views
1

チュートリアルを参考にして作成したカスタムコーデック-https://docs.datastax.com/en/latest-java-driver/java-driver/reference/customCodecs.htmlを定義しました。ここに私のコーデックimpelementationがある: -Java Cassandra Datastaxドライバのカスタムコーデックでコレクションタイプが処理されない

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メソッドでは、私は(user.getUserId()を使用して)ユーザーIDの文字列を抽出した後、ユーザーID列として私のカサンドラテーブルに保管しようとしています。逆直列化では、指定されたByteBufferインスタンスを文字列に変換して返します。 これは、シリアライズ時にstring、set、listに対して完璧に機能します(つまり、Setを使用している場合、コーデックはsetの各要素に対してserialize()を実行し、対応する文字列をmy casandraテーブルに格納します)。しかし、cassandraのセットフィールドをデシリアライズする際、deserializeメソッドはByteBufferオブジェクトのセット全体を送信します。 ByteBufferオブジェクトを解析することで個々の要素がそこにあることがわかります。 deserializeは、セットのすべての要素に対して実行されることに注意してください。したがって、セットに5つの要素がある場合、deserializeは5回実行されますが、毎回、ByteBuffer内の特定の要素を送信する代わりに、セット全体が送信されます。 これがなぜやっているのかわからないし、Googleもそれほど助けになっていない。どんな提案/解決策も、私がかなり長い間これに取り組んでいたので、大歓迎です。

ありがとうございます!

答えて

1

AbstractCollectionCodecは、SetCodecListCodecがコレクションのシリアライズ/デシリアライズに使用するものです。逆シリアル化すると、要素の開始位置(ByteBuffer.position())に配置され、個々の要素の末尾(ByteBuffer.limit())から基底の要素コーデック(この場合はUserCodec)に限定された全体のByteBufferが渡されます。

buffer.array()に電話すると、位置または制限にかかわらず、ByteBufferのバッキングアレイ全体が取得されます。

あなたはあなたのlimitposition、間のデータのバイト配列を返すBytes.getArray(ByteBuffer)を使用することであるため、より良い動作するはず何すなわち:あなたは、単にC *であなたのUserインスタンスを格納しているので

@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; 
} 

あなたの代わりに何ができるかそのgetUserId()を表す文字列はつまり、単にUser <-> String (UserId)をマップエクストラモジュールからMappingCodecのインスタンスを作成します

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(); 
    } 
} 

MappingCodecon the docs siteについて詳しく読むことができます。

+0

ありがとうございました!それは本当に役に立ちました! –

関連する問題