我想在SQLite数据库中存储一个图像(大小约10MB) . 为此,我创建了一个DB助手,一个Dao . 一切正常,我可以创建几个记录并毫无问题地阅读它们,我甚至可以毫无问题地更新最新记录中的blob .
但是,如果我回到较旧的记录并更新blob,我无法再使用blob加载此记录 .
我有一个列表视图,我显示所有记录,为此我使用一个不返回blob的选择 . 此列表工作正常,但是当我单击列表中的项目时,我尝试使用blob加载记录,光标返回0行 .
public void save(Bill aBill) {
ContentValues values = new ContentValues();
values.put(DatabaseHelper.BILL_NAME_COLUMN, aBill.getName());
values.put(DatabaseHelper.BILL_DUE_DATE_COLUMN, getContentValue(aBill.getDueDate()));
values.put(DatabaseHelper.BILL_IMAGE_COLUMN, aBill.getImage());
if (!aBill.isPersistent()) {
aBill.setId(database.insert(DatabaseHelper.BILL_TABLE, null, values));
aBill.setPersistent(true);
} else {
database.update(DatabaseHelper.BILL_TABLE, values, DatabaseHelper.BILL_ID_COLUMN + "=?", new String[]{String.valueOf(aBill.getId())});
}
}
// fails after updating the blob
public Bill get(long id) {
Cursor cursor = database.query(DatabaseHelper.BILL_TABLE,
new String[]{DatabaseHelper.BILL_ID_COLUMN, DatabaseHelper.BILL_NAME_COLUMN, DatabaseHelper.BILL_DUE_DATE_COLUMN, DatabaseHelper.BILL_IMAGE_COLUMN}, "id = ?", new String[] {String.valueOf(id)}, null,
null, DatabaseHelper.BILL_DUE_DATE_COLUMN);
Bill bill = null;
while (cursor.moveToNext()) {
bill = new Bill();
bill.setPersistent(true);
bill.setId(cursor.getLong(cursor.getColumnIndex(DatabaseHelper.BILL_ID_COLUMN)));
bill.setName(cursor.getString(cursor.getColumnIndex(DatabaseHelper.BILL_NAME_COLUMN)));
bill.setDueDate(getDate(cursor.getString(cursor.getColumnIndex(DatabaseHelper.BILL_DUE_DATE_COLUMN))));
bill.setImage(cursor.getBlob(cursor.getColumnIndex(DatabaseHelper.BILL_IMAGE_COLUMN)));
}
cursor.close();
return bill;
}
//works fine after updating the blob
public List findAll() {
List bills = new ArrayList();
Cursor cursor = database.query(DatabaseHelper.BILL_TABLE,
new String[]{DatabaseHelper.BILL_ID_COLUMN, DatabaseHelper.BILL_NAME_COLUMN, DatabaseHelper.BILL_DUE_DATE_COLUMN}, null, null, null,
null, DatabaseHelper.BILL_DUE_DATE_COLUMN);
while (cursor.moveToNext()) {
Bill bill = new Bill();
bill.setPersistent(true);
bill.setId(cursor.getLong(cursor.getColumnIndex(DatabaseHelper.BILL_ID_COLUMN)));
bill.setName(cursor.getString(cursor.getColumnIndex(DatabaseHelper.BILL_NAME_COLUMN)));
bill.setDueDate(getDate(cursor.getString(cursor.getColumnIndex(DatabaseHelper.BILL_DUE_DATE_COLUMN))));
bills.add(bill);
}
cursor.close();
return bills;
}
这是例外:
java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
at android.database.CursorWindow.nativeGetLong(Native Method)
at android.database.CursorWindow.getLong(CursorWindow.java:511)
at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75)
at net.rka.android.billreminder.BillDao.get(BillDao.java:106)
我怀疑连续更新blob会以某种方式破坏数据库 .
有没有人遇到过类似的问题?如果是这样,你是如何解决的?
1 回答
您的问题很可能是由于图像的大小和怪癖,因为想要更好的术语,您可以存储2m的大型BLOB 's without issue, but due to the size limitations of an Android'光标窗口,您可能无法检索BLOB . 这有时会使一些SQLiteDatabase / Cursor(在这种情况下为Cursor
getBlob()
或它的底层方法)基本上隐藏底层故障,以提供通常更简单的开发体验 .如果您使用了SQLiteDatabase
DatabaseUtils.dumpCursor
,则可能会突出显示SQLiteDatabase查询便捷方法可能已隐藏的问题 . 所以补充: -可以提供线索 .
我可以想到3个选项: -
不是将文件存储为BLOBS,而是将文件作为文件存储在磁盘上并将路径存储在数据库中 .
显着减小图像的大小 .
查看使用C和本机SQLIte3库将BLOBS检索到适当大小的容器中 .
也许可能是一些图书馆这样做 . 但是,我不记得有任何提及 .