【问题标题】:Serialize java class with custom object attributes使用自定义对象属性序列化 java 类
【发布时间】:2013-07-26 15:36:49
【问题描述】:

我想使用 Ebean ORM 在我的 MySQL 数据库上序列化一个 Java 类。

我的类定义类似于以下:

public class Test implements Serializable
{
    @Id
    private Long id;
    ...
    ...
    ...
    @Lob
    private MyClass1 obj1;
    @Lob
    private MyClass2 obj2;
    ...
    ...
    //getters and setters
}

我的类 MyClass1 和 MyClass2 基本上是一个

float[] 

还有一个

Hashmap<String, Float> 

并且都实现了 Serializable 接口。

我不想创建一个类:

@Lob
byte[] obj1bytes;
@Transient
MyClass1 obj1Obj;
@Lob
byte[] obj2bytes;
@Transient
MyClass2 obj2Obj;
//getters and setters

我想要获得的是自动序列化和反序列化这个类,而不必使用 byte[] 数组将我的测试类中的 obj1 和 obj2 保存到两个 LongBlob 字段中的 MySQL 表中

Ebean.save(testClassInstance);
Ebean.find(Test.class, ID);

EDIT1:MyClass1 定义如下:

public class MyClass1 implements Interface1 {
    private float[] vector;
    public MyClass1 () {
    }
    public MyClass1 (float[] vector) {
        this.vector = vector;
    }
    public float[] getVector() {
        return vector;
    }
    public void setVector(float[] vector) {
       this.vector = vector;
    }
    @Override
    public byte[] serialize() throws Exception {
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteOut);
        out.writeObject(object);
        out.close();            
        return byteOut.toByteArray();
    }
    @Override
    public void deserialize(byte[] bytes) throws Exception {
        ByteArrayInputStream byteInt = new ByteArrayInputStream(bytes);
        ObjectInputStream out = new ObjectInputStream(byteInt);
        vector = (float[])out.readObject();
    }
    @Override
    public float cossim(MyClass1 v) throws Exception {
        method logic
    }
    @Override
    public MyClass1 add(MyClass1 v) throws Exception {
        method logic
   }
}

MyClass2 被定义为 MyClass1,只是我有一个 HashMap () 而不是 float[] 向量。唯一值得注意的区别是 serialize() 和 deserialize():

@Override
public byte[] serialize() throws Exception {
    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    DataOutputStream out = new DataOutputStream(outStream);
    out.writeInt(map.size());
    Iterator<String> iterator = map.keySet().iterator();
    while (iterator.hasNext()) {
        String key = iterator.next();
        out.writeUTF(key);
        out.writeFloat(map.get(key));
    }
    return outStream.toByteArray();
}

@Override
public void deserialize(byte[] bytes) throws Exception {
    try {
      ByteArrayInputStream inStream = new ByteArrayInputStream(bytes);
      DataInputStream in = new DataInputStream(inStream);
      this.map = new HashMap<>();
      int n = in.readInt();
      for (int i = 0; i < n; i++) {
        map.put(in.readUTF(), in.readFloat());
      }
    } catch (Exception ex) {
      throw ex;
    }
}

【问题讨论】:

    标签: java mysql serialization ebean


    【解决方案1】:

    实际上,float[]HashMap&lt;String,float&gt; 不需要包装,因为它们本身是可序列化的。

    另一件事是,如果MyClass1MyClass2 是可序列化的,那么您可以使用@Lob。根据this wikibook

    默认情况下,在 JPA 中任何不是 关系或基本类型(字符串、数字、时间、原始), 将被序列化为 BLOB 字段。

    在那本 wikibook 中,还有一个使用 @Lob 来表示 Image 类的示例。

    @Entity
    public class Employee {
        ...
        @Basic(fetch=FetchType.LAZY)
        @Lob
        private Image picture;
        ...
    }
    

    希望这对你有帮助。

    【讨论】:

    • 感谢您的回复。实际上,我已经阅读了该维基书并做了完全相同的事情:我用@Lob 注释了我的 MyClass1 和 MyClass2 对象,但是当我执行 Ebean.save(testInstance) 时,除了这两个之外,每个字段都保存在数据库中。我需要包装这些 float[] 和 HashMap 因为它们需要对它们进行一些需要创建两个类的特定操作。
    • @Andrea 你能发布你的 MyClass1 和 MyClass2 吗?
    • 我修改了我的问题以包括 MyClass1 和 MyClass2 定义(实际上大部分)
    【解决方案2】:

    在您回复后我做了一些编码。

    条件:ClassB的字段应该是可序列化的,fields的字段应该是可序列化的并且......

    B 类:

    import java.io.Serializable;
    
    public class ClassB implements Serializable{
        private static final long serialVersionUID = 1L;
        String b;
    
        public String getB() {
            return b;
        }
    
        public void setB(String b) {
            this.b = b;
        }
    
    }
    

    A 类:

    import java.io.Serializable;
    
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Lob;
    
    @Entity
    public class ClassA implements Serializable{
        private static final long serialVersionUID = 1L;
        @Id
        String a;
        @Lob
        ClassB b;
    
        public String getA() {
            return a;
        }
        public void setA(String a) {
            this.a = a;
        }
        public ClassB getB() {
            return b;
        }
        public void setB(ClassB b) {
            this.b = b;
        }
    
    }
    

    这里,ClassA 包含 ClassB 对象。您可以在 ClassB 中添加任何逻辑并且它可以工作。我对您覆盖序列化和反序列化有一个小问题。我认为你不需要这样做。它会在序列化时默认完成。最后,这些代码确实像我尝试过的那样工作。

    希望这会对你有所帮助。

    【讨论】:

    • 我试过你的确切代码,但它不起作用。你能分享你的ebean.properties吗? Ebean 不会在我的 MySQL 数据库中创建 LOB 列。你运行过你的示例代码吗?您使用了哪些组件?您使用的是哪个版本的 Ebean 库?
    • 完全没有错误,Ebean 完全忽略了我所有不是 byte[] 的 Lob。
    • 其实我用的是Hibernate。
    • 我想我清楚地表明我正在使用 Ebean,而不是 Hibernate...你至少可以告诉我你正在使用 Hibernate,所以我不会花时间试图弄清楚为什么我无法让它工作,但你是......
    • 我刚看了ORM,接下来我对Ebean一无所知。很抱歉。
    猜你喜欢
    • 1970-01-01
    • 2021-08-22
    • 1970-01-01
    • 2010-11-18
    • 1970-01-01
    • 1970-01-01
    • 2016-06-20
    • 1970-01-01
    • 2015-07-27
    相关资源
    最近更新 更多