在自定义持久化器的 sqlArgToJava 中处理 NULL 情况 class

handle NULL case inside sqlArgToJava of custom persister class

我在我的一个项目中使用 ormlite,我有一个 class A 和自定义类型 F 的字段 f 并且我有要求该字段 f 在任何情况下都不应该为空。所以我想在数据库文件

中的字段 f 为 NULL 时实例化 class F 的新对象
class A {
    @DatabaseField(columnName = "xyz", persisterClass = FieldPersister.class)
    F f;

    public A() {
        f = new F();
    }
}

根据文档,我使用自定义持久化器 class FieldPersister 并尝试在那里进行空检查。

class FieldPersister extends StringType {
    public Object javaToSqlArg(FieldType fieldType, Object javaObject) {
        ...
    }

    public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos) {
        if (sqlArg == null) return new F();
        else {
            String value = (String) sqlArg;
            return new F(value);
        }
    }
}

我试过调试程序,发现下面的方法中已经有null检查

resultToJava(FieldType fieldType, DatabaseResults results, int columnPos)

即使重写此方法也没有解决导致我提出问题的问题,有什么方法可以处理这种情况,还是我遗漏了部分难题?

使用 SSCCE 更新:

pom.xml

Main.java

StringPropertyPersister.java

Even overriding this method didn't resolved the issue which leads to my question, is there any way to handle this situation or am I missing some part of the puzzle?

您漏掉了拼图的一部分,而且非常微妙。不幸的是 ResultSet.getInt(...) 方法 return 是 int。为什么这很重要?因为 ORMLite 无法判断数据库中的字段是 NULL 还是原始字段。所以通常发生的情况是 ORMLite 从 ResultSet 获取结果,要求它由自定义转换器转换,然后 ORMLite 查看它是否为 null 并适当地调整值。也许有更好的方法来做到这一点。我需要考虑一下。

这里有几个解决方案。

  1. 在您的字段定义中添加 defaultValue = ""。如果磁盘上有 NULL 值,这将无法处理这种情况,但如果您使用 dao.create(...),它将起作用。然后,您可以使用 FieldConverter.parseDefaultString(...) 定义要在字段为空时插入的默认对象。

  2. 在您的 A.getValue() 方法中,您在那里执行 null 检查,如果它为 null,则 return 一个 new SimpleStringProperty("")。但是你的示例代码可能过于简单了。

  3. 破解方法是重写 resultToJava(...) 方法,使其类似于:

    @Override
    public Object resultToJava(FieldType fieldType, DatabaseResults results,
            int columnPos) throws SQLException {
        // remove the null check here so we can handle the null
        Object value = resultToSqlArg(fieldType, results, columnPos);
        return sqlArgToJava(fieldType, value, columnPos);
    }
    

    但您还需要覆盖以下内容,这是一个 hack。

    @Override
    public boolean isStreamType() {
        // this forces the null check to be ignored
        return true;
    }
    

    这是一个 hack,因为如果 ORMLite 巧妙地改变它处理 "stream" SQL 类型的方式,它可能会破坏你的代码。

    在此处查看我的测试版本:CustomFieldNullTest.java