无法在 ActiveAndroid 中保存空列值
Cannot save null column value in ActiveAndroid
为了简单起见,我有这个模型:
@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; }
}
我的测试失败了:
//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
我似乎无法在 ActiveAndroid 中将列值从任何值更改为 null。很奇怪。这是一个错误吗?我没有找到任何关于它的信息,但这个功能看起来很基本。
如果我调试应用程序并按照保存方法,它到达的最后一个命令在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);
....
}
我无法进一步查看,因为 "nativeBindNull" 不可用
终于找到原因了,问题出在ActiveAndroid库
空值已正确保存到 DDBB,但未正确检索。由于 ActiveAndroid 使用缓存项,因此在获取元素时,它会获取 "old version" 并使用新值更新它。这是库失败的地方,因为正在检查如果不是 null 则替换值,否则什么都没有。
要解决这个问题,我们必须从库中更改它,在 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);
}
....
}
....
}
为了简单起见,我有这个模型:
@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; }
}
我的测试失败了:
//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
我似乎无法在 ActiveAndroid 中将列值从任何值更改为 null。很奇怪。这是一个错误吗?我没有找到任何关于它的信息,但这个功能看起来很基本。
如果我调试应用程序并按照保存方法,它到达的最后一个命令在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);
....
}
我无法进一步查看,因为 "nativeBindNull" 不可用
终于找到原因了,问题出在ActiveAndroid库
空值已正确保存到 DDBB,但未正确检索。由于 ActiveAndroid 使用缓存项,因此在获取元素时,它会获取 "old version" 并使用新值更新它。这是库失败的地方,因为正在检查如果不是 null 则替换值,否则什么都没有。
要解决这个问题,我们必须从库中更改它,在 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);
}
....
}
....
}