2

To make it simple, I have this model:

@Table(name = "Items")
class TItem extends Model {
    @Column(name = "title")
    private String      mTitle;

    public String getTitle() { return mTitle; }

    public void setTitle(String title) { mTitle = title; }
}

And I'm failing in my testings doing that:

    //Create new object and save it to DDBB
    TItem r = new TItem();
    r.save();

    TItem saved = new Select().from(TItem.class).where("id=?", r.getId()).executeSingle();
    //Value for saved.getTitle() = null  --> OK

    r.setTitle("Hello");
    r.save();
    saved = new Select().from(TItem.class).where("id=?", r.getId()).executeSingle();
    //Value for saved.getTitle() = "Hello"  --> OK

    r.setTitle(null);
    r.save();
    saved = new Select().from(TItem.class).where("id=?", r.getId()).executeSingle();
    //Value for saved.getTitle() = "Hello"  --> FAIL

It seems I cannot change a column value from anything to null in ActiveAndroid. Very strange. Is it a bug? I didn't find anything about it, but looks pretty basic this functionallity.

If I debug the app and follow the saving method, the last command it reaches is in SQLLiteConnection.java:

private void bindArguments(PreparedStatement statement, Object[] bindArgs) {
    ....
    // It seems ok, as it is really inserting a null value in the DDBB
    case Cursor.FIELD_TYPE_NULL:
        nativeBindNull(mConnectionPtr, statementPtr, i + 1);
    ....
}

I cannot see further, as "nativeBindNull" is not available

Corbella
  • 1,791
  • 14
  • 24

2 Answers2

3

Finally I found what happened, and the problem is in ActiveAndroid library.

The null value is saved propertly to DDBB, but is not retrieved correctly. As ActiveAndroid uses cached items, when getting an element, it gets an "old version" and updates it with the new values. Here is where the library fails, because is checking that if not null replace the value, otherwise, nothing.

To solve this, we'll have to change it from the library, in the class Model.java:

public final void loadFromCursor(Cursor cursor) {

    List<String> columnsOrdered = new ArrayList<String>(Arrays.asList(cursor.getColumnNames()));
    for (Field field : mTableInfo.getFields()) {
        final String fieldName = mTableInfo.getColumnName(field);
        Class<?> fieldType = field.getType();
        final int columnIndex = columnsOrdered.indexOf(fieldName);
        ....

        if (columnIsNull) {
            <strike>field = null;</strike> //Don't put the field to null, otherwise we won't be able to change its content
            value = null;
        }

        ....

        <strike>if (value != null)</strike> {   //Remove this check, to always set the value
            field.set(this, value);
        }
        ....
    }
    ....
}
Corbella
  • 1,791
  • 14
  • 24
0

You can save field\fields by Update object:

Update(YourModelClass::class.java)
        .set("field_one = ${value1}, field_second = $value2")
        .where("id = ?", model.id)
        .execute()

If you add quotes then the values will be saved as text:

Update(YourModelClass::class.java)
        .set("field_one = '$value1', field_second = '$value2'")
        .where("id = ?", model.id)
        .execute()
AlexS
  • 918
  • 1
  • 12
  • 28