Java – Why can’t isNotNull be executed on columns with DataType.SERIALIZABLE in ormlite?

Why can’t isNotNull be executed on columns with DataType.SERIALIZABLE in ormlite?… here is a solution to the problem.

Why can’t isNotNull be executed on columns with DataType.SERIALIZABLE in ormlite?

With ORMLite 4.48 on Android, consider the following user table….

@DatabaseTable(tableName = "users")
public class User {

@DatabaseField(columnName = Column.UUID)
    protected String uuid;

@DatabaseField(columnName = Column.FIRST_NAME)
    protected String firstName = null;

@DatabaseField(columnName = Column.LAST_NAME)
    protected String lastName = null;

@DatabaseField(columnName = Column.ADDRESS, dataType = DataType.SERIALIZABLE)
    protected Address address = null;

// ...
}

(Address classes represent human-readable addresses, converted from latitude/longitude).

… Use the following query….

<pre class=”lang-java prettyprint-override”>List<User> users = getDbHelper().getDao(User.class)
.queryBuilder()
.where()
.isNotNull(User.Column.ADDRESS)
.query();

… This exception is thrown:

java.sql.SQLException: Field 'address' is of data type com.j256.ormlite.field.types.SerializableType@42ac7650 which can not be compared
        at com.j256.ormlite.stmt.query.BaseComparison.<init>(BaseComparison.java:27)
        at com.j256.ormlite.stmt.query.IsNotNull.<init>(IsNotNull.java:19)
        at com.j256.ormlite.stmt.Where.isNotNull(Where.java:315)
        ...

Obviously, the IS NOT NULL clause cannot be used for fields stored as DataType.SERIALIZABLE.

Digging into the ORMLite code, the BaseComparison constructor checks whether the fieldType is comparable:

https://github.com/j256/ormlite-core/blob/master/src/main/java/com/j256/ormlite/stmt/query/BaseComparison.java

protected BaseComparison(String columnName, FieldType fieldType, Object value, boolean isComparison)
        throws SQLException {
    if (isComparison && fieldType != null && !fieldType.isComparable()) {
        throw new SQLException("Field '" + columnName + "' is of data type " + fieldType.getDataPersister()
                + " which can not be compared");
    }

...
}

Obviously, SerializableType.isComparable() returns false:

https://github.com/j256/ormlite-core/blob/master/src/main/java/com/j256/ormlite/field/types/SerializableType.java

@Override
public boolean isComparable() {
    return false;
}

So, it’s clear to me why the exception is thrown. But why can’t you do Where.isNull() or Where.isNotNull()? Is this a limitation of SQLite or did the author of ORMLite make this decision?

Solution

Not sure “why”, but I believe the “how” is to use ForeignCollectionField instead of DatabaseField

Related Problems and Solutions