如何在Oracle中使用Kryo将非常大的Java对象保存到Blob中并避免KryoException缓冲区溢出?

时间:2018-04-18 18:20:44

标签: java serialization oracle11g blob kryo

我正在尝试使用Kryo保存一个非常大的对象,

public static byte[] toBytes(KryoPool kryoPool, Object object) {
    try (Output output = new Output(32768, Integer.MAX_VALUE - 8)) {
        kryoPool.run(kryo -> {
            kryo.setReferences(false);
            kryo.writeObject(output, object);
            return null;
        });
        return output.toBytes();
    }
}

我得到例外:

com.esotericsoftware.kryo.KryoException: Buffer overflow. Available: 0, required: 1
    at com.esotericsoftware.kryo.io.Output.require(Output.java:167)
    at com.esotericsoftware.kryo.io.Output.writeByte(Output.java:225)
    at com.esotericsoftware.kryo.Kryo.writeObjectOrNull(Kryo.java:623)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:86)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:508)
    at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:651)
    at com.esotericsoftware.kryo.serializers.CollectionSerializer.write(CollectionSerializer.java:100)
    at com.esotericsoftware.kryo.serializers.CollectionSerializer.write(CollectionSerializer.java:40)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:575)
    at com.esotericsoftware.kryo.serializers.ObjectField.write(ObjectField.java:79)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:508)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:557)

然后应将此字节数组保存到Oracle表Blob字段中。 我现在意识到两件事:

  1. byte []的大小有限,不能大于2 ^ 31-1?我应该如何处理大于最大尺寸的非常大的物体。字节数组?
  2. 如何避免Kryo Buffer溢出异常?
  3. 更新: 非常感谢。我只是想知道我应该在哪个方面调用Kryo序列化:

        try (final PreparedStatement pstmt = conn.prepareStatement("INSERT INTO DATA_STORAGE (ID, VALUE) VALUES (?, ?)")) 
    {
            final Blob blob = conn.createBlob();
            OutputStream out = blob.setBinaryStream(0L);
    
            Output output = new Output(out);
    
            pstmt.setInt(1, id);
            pstmt.setBlob(2, blob);
    
            //probably here?   
            kryoPool.run(kryo -> {
                kryo.setReferences(false);
                kryo.writeObject(output, object);
                return null;
            });
    
            pstmt.executeUpdate();
    }
    

1 个答案:

答案 0 :(得分:1)

不要创建中间byte[],而是直接流式传输到BLOB:

try (Output output = new Output(blob.setBinaryStream(0L))) {
    ....
}