在自定义持久化类的sqlArgToJava中处理NULL case

时间:2016-07-14 10:25:55

标签: java javafx-8 ormlite

我在我的某个项目中使用了ormlite,并且我有一个类A,其字段为f自定义类型F,我要求字段{{1}在任何情况下都不应为null。因此,只要数据库文件中的字段f为NULL,我就想实例化F类的新对象

f

根据我使用自定义持久化类class A { @DatabaseField(columnName = "xyz", persisterClass = FieldPersister.class) F f; public A() { f = new F(); } } 并尝试在那里进行空检查的文档。

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

即使重写这种方法也没有解决导致我的问题的问题,有没有办法处理这种情况或者我错过了一些难题?

使用SSCCE更新:

pom.xml

Main.java

StringPropertyPersister.java

1 个答案:

答案 0 :(得分:0)

  

即使重写这种方法也没有解决导致我的问题的问题,有没有办法处理这种情况或者我错过了一些难题?

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

这里有几个解决方案。

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

  2. A.getValue()方法中,您在那里进行null检查,如果为空则返回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);
    }
    

    但你还需要覆盖以下哪个是黑客。

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

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

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