【问题标题】:How to specify object custom serialization in ORMLite?如何在 ORMLite 中指定对象自定义序列化?
【发布时间】:2015-04-19 17:41:14
【问题描述】:

我想将一些 ParentClass 类型的字段作为 json 字符串存储到我的数据库中。我不想使用 Serializable 接口和 DataType.SERIALIZABLE ,因为它与序列化类的完整类名相关。

所以我使用以下代码:

class ParentClass {

    @DatabaseField(persisterClass = MyFieldClassPersister.class)
    private MyFieldClass myField;
}

其中持久化类是一种:

public class MyFieldClassPersister extends StringType {

    private static final MyFieldClassPersister singleTon = new MyFieldClassPersister();

    public static MyFieldClassPersister getSingleton() {
        return singleTon;
    }

    protected MyFieldClassPersister() {
        super(SqlType.STRING, new Class<?>[0]);
    }

    @Override
    public Object parseDefaultString(FieldType fieldType, String defaultStr) {
        return jsonStringToObject(defaultStr);
    }

    @Override
    public Object resultToSqlArg(FieldType fieldType, DatabaseResults results, int columnPos) throws SQLException {
        String string = results.getString(columnPos);
        return jsonStringToObject(string);
    }

    private static MyFieldClass jsonStringToObject(String string) {
        // json to object conversion logic
    }

}

这是我遇到的两个问题:

  1. 我不知道如何指定从对象到字符串的自定义转换。似乎 ORMLite 调用 Object.toString() 以获取对象的字符串表示形式。在 Persister 中有一些方法会很棒,我可以在其中指定如何将 Object 转换为字符串(在我的情况下为 json)。是的,我可以在 MyFieldClass 中重写 toString() 方法,但是在 Persister 中进行转换更方便。是否有任何方法可以重写以指定从模型对象到 db-object 的转换?

  2. 如果我将自定义字段类型标记为字符串类型:

    class ParentClass {
    
        @DatabaseField(dataType = DataType.STRING, persisterClass = MyFieldClassPersister.class)
        private MyFieldClass myField;
    }
    

然后 ormlite 在保存对象时崩溃并显示以下消息:

java.lang.IllegalArgumentException: Field class com.myapp.venue.MyFieldClass for
    field FieldType:name=myField,class=ParentClass is not valid for type
    com.j256.ormlite.field.types.StringType@272ed83b, maybe should be
    class java.lang.String

如果我省略 dataType 规范,它不会崩溃。我可以以某种方式避免这种崩溃吗?在我看来,最好明确指定类型。

【问题讨论】:

  • 是的,ORMLite 没有做toString()。是StringType 正在这样做。您还需要重写并实现javaToSqlArg(...) 方法。

标签: java json serialization ormlite


【解决方案1】:

所以基本上你的持久化器应该以下面的方式实现:

public class MyFieldClassPersister extends StringType {

    private static final MyFieldClassPersister INSTANCE = new MyFieldClassPersister();

    private MyFieldClassPersister() {
        super(SqlType.STRING, new Class<?>[] { MyFieldClass.class });
    }

    public static MyFieldClassPersister getSingleton() {
        return INSTANCE;
    }

    @Override
    public Object javaToSqlArg(FieldType fieldType, Object javaObject) {
        MyFieldClass myFieldClass = (MyFieldClass) javaObject;
        return myFieldClass != null ? getJsonFromMyFieldClass(myFieldClass) : null;
    }

    @Override
    public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos) {
        return sqlArg != null ? getMyFieldClassFromJson((String) sqlArg) : null;
    }

    private String getJsonFromMyFieldClass(MyFieldClass myFieldClass) {
        // logic here
    }

    private MyFieldClass getMyFieldClassFromJson(String json) {
        // logic here
    }
}

您应该在 OrmLiteSqliteOpenHelper 类的 onCreate 方法中注册它

    @Override
    public void onCreate(SQLiteDatabaseHolder holder, ConnectionSource connectionSource) {
            try {
                //...
                DataPersisterManager
                 .registerDataPersisters(MyFieldClassPersister.getSingleton());
            } catch (SQLException e) {
                // log exception
            }
    }

然后你可以像这样在你的模型中使用它:

@DatabaseField(persisterClass = MyFieldClassPersister.class, columnName = "column_name")
protected MyFieldClass myFieldClass;

【讨论】:

  • 感谢您的回复,非常有帮助。我不能使用OrmLiteSqliteOpenHelper,因为它属于 Android 版本的 ORMLite(我正在开发桌面应用程序)。至于第二个问题,我还不清楚。我采用了您的实现方式并尝试明确指定列类型 - @DatabaseField(dataType = DataType.STRING, persisterClass = MyFieldClassPersister.class)。但 ORMLite 崩溃时出现同样的异常。
  • 我已经为简单的 java 应用程序尝试过它,它按预期工作。您不需要在注释中添加dataType = DataType.STRING,我添加此参数时也有同样的异常。此外,您不需要注册持久性。您只需要:@DatabaseField(persisterClass = MyFieldClassPersister.class) protected MyFieldClass myFieldClass;
【解决方案2】:

不要在 onCreate() 方法中注册持久化适配器。仅在首次创建数据库时调用此方法。您应该将其添加到其他地方,例如您的构造函数或 onOpen() 方法。

【讨论】:

    猜你喜欢
    • 2016-05-07
    • 2014-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多