SQLite 数据库插入以某种方式消失了?
SQLite database insert is somehow vanishing?
我的 Android 应用程序遇到一个非常奇怪的问题,当我向数据库 table 插入一个值时,第一个条目不知何故消失了。但是,任何后续条目都显示正常。
更具体一点,我的应用程序的一部分允许用户创建一个简单的日志,他们可以在其中输入一些文本,当他们保存它时,它会显示在日志条目列表中。但是,当我尝试将第一个条目插入空 table 时,该条目没有显示,当我查询计数时数据库也没有指示有任何数据。
有趣的是,当我查看数据库插入调用 (SQLiteDatabase.insert()) 的 return 时,我看到一个有效的行号 returned。事实上,当我查看我保存到数据库中的任何日志条目时,行号都在正确递增。根据文档,我的理解是,如果 returned 是非负数,则插入成功。
下面的代码从我的 AlertDialog 中获取 EditText 的结果,创建一个新的日志条目,并调用插入方法:
newPainLogEntryDialog.setPositiveButton("Save",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//make new pain log entry
PainLog painLog = new PainLog();
painLog.setPainEntry(input.getText().toString());
painLog.setPainDateTime(Calendar.getInstance());
Database.init(PainLogTab.this.getActivity());
Database.createPainLog(painLog);
updatePainLogList();
//display success to user
Toast.makeText(PainLogTab.this.getActivity(),
"Log entry saved", Toast.LENGTH_SHORT).show();
}
});
Database.createPainLog() 的代码:
public static long createPainLog(PainLog painLog) {
ContentValues cv = new ContentValues();
cv.put(COLUMN_PAINLOG_ENTRY, painLog.getPainEntry());
cv.put(COLUMN_PAINLOG_DATETIME, painLog.getPainDateTimeString());
return getDatabase().insert(PAINLOG_TABLE, null, cv);
}
Toast 消息之前的最后一次调用是 updatePainLogList(),它获取所有 DB 条目:
public void updatePainLogList(){
Database.init(PainLogTab.this.getActivity());
final List<PainLog> painLogs = Database.getAllPainLogs();
painLogListAdapter.setPainLogs(painLogs);
Log.d(getClass().getSimpleName(), "number of painLogs found: " + painLogs.size());
getActivity().runOnUiThread(new Runnable() {
public void run() {
// reload content
PainLogTab.this.painLogListAdapter.notifyDataSetChanged();
if(painLogs.size() > 0){
getView().findViewById(android.R.id.empty).setVisibility(View.INVISIBLE);
}else{
getView().findViewById(android.R.id.empty).setVisibility(View.VISIBLE);
}
}
});
}
为了完成,getAll() 的主体及其附带的方法 getCursor():
public static Cursor getPainLogCursor() {
String[] columns = new String[] {
COLUMN_PAINLOG_ID,
COLUMN_PAINLOG_ENTRY,
COLUMN_PAINLOG_DATETIME
};
return getDatabase().query(PAINLOG_TABLE, columns, null, null, null, null,
null);
}
public static List<PainLog> getAllPainLogs() {
List<PainLog> painLogs = new ArrayList<PainLog>();
Cursor cursor = Database.getPainLogCursor();
if (cursor.moveToFirst()) {
while (cursor.moveToNext()) {
PainLog painLog = new PainLog();
painLog.setId(cursor.getInt(IDX_PAINLOG_ID));
painLog.setPainEntry(cursor.getString(IDX_PAINLOG_ENTRY));
painLog.setPainDateTime(cursor.getString(IDX_PAINLOG_DATETIME));
painLogs.add(painLog);
}
}
cursor.close();
return painLogs;
}
现在我可以通过一些代码来解释到目前为止我采取了哪些调试步骤。如上所述,当我查看数据库插入的 return 时,我得到一个非零的正数。但是,当我尝试在紧随其后的更新方法中打印日志数量时(没有删除或在途中调用任何东西),它显示 0,实际上,如果我跟随 Cursor,我发现它永远不会进入添加日志的循环到显示的列表,也表明它没有选择条目。
我曾尝试在事务中设置数据库插入,以便我可以手动提交,但这也无济于事。让我觉得更有趣的是,我在我的应用程序的其他地方有类似的功能,我保存用户首选项并将它们显示在列表中,这不会遇到同样的问题......我已经与这段代码进行了比较并且不能'找不到任何会导致它的差异。
总而言之,我的问题有两个:为什么只有我第一次插入空 table 时显示不存在,而后面的所有插入都很好?为什么我从数据库插入中获得了有效的 return,但当我查询丢失的数据时却立即跟随插入?
提前感谢您提供的任何帮助:)
if (cursor.moveToFirst()) {
while (cursor.moveToNext()) {
这将跳过游标中的第一行。 moveToFirst()
移动到第一行,moveToNext()
移动到下一行,跳过第一行。
您可以将其替换为 while (cursor.moveToNext())
。当您从查询中获取游标时,它首先放置在索引 -1 处,即第一个之前的行。
if (cursor.moveToFirst()) {
while (cursor.moveToNext()) {
这将是最好的解决方案....
我的 Android 应用程序遇到一个非常奇怪的问题,当我向数据库 table 插入一个值时,第一个条目不知何故消失了。但是,任何后续条目都显示正常。
更具体一点,我的应用程序的一部分允许用户创建一个简单的日志,他们可以在其中输入一些文本,当他们保存它时,它会显示在日志条目列表中。但是,当我尝试将第一个条目插入空 table 时,该条目没有显示,当我查询计数时数据库也没有指示有任何数据。
有趣的是,当我查看数据库插入调用 (SQLiteDatabase.insert()) 的 return 时,我看到一个有效的行号 returned。事实上,当我查看我保存到数据库中的任何日志条目时,行号都在正确递增。根据文档,我的理解是,如果 returned 是非负数,则插入成功。
下面的代码从我的 AlertDialog 中获取 EditText 的结果,创建一个新的日志条目,并调用插入方法:
newPainLogEntryDialog.setPositiveButton("Save",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//make new pain log entry
PainLog painLog = new PainLog();
painLog.setPainEntry(input.getText().toString());
painLog.setPainDateTime(Calendar.getInstance());
Database.init(PainLogTab.this.getActivity());
Database.createPainLog(painLog);
updatePainLogList();
//display success to user
Toast.makeText(PainLogTab.this.getActivity(),
"Log entry saved", Toast.LENGTH_SHORT).show();
}
});
Database.createPainLog() 的代码:
public static long createPainLog(PainLog painLog) {
ContentValues cv = new ContentValues();
cv.put(COLUMN_PAINLOG_ENTRY, painLog.getPainEntry());
cv.put(COLUMN_PAINLOG_DATETIME, painLog.getPainDateTimeString());
return getDatabase().insert(PAINLOG_TABLE, null, cv);
}
Toast 消息之前的最后一次调用是 updatePainLogList(),它获取所有 DB 条目:
public void updatePainLogList(){
Database.init(PainLogTab.this.getActivity());
final List<PainLog> painLogs = Database.getAllPainLogs();
painLogListAdapter.setPainLogs(painLogs);
Log.d(getClass().getSimpleName(), "number of painLogs found: " + painLogs.size());
getActivity().runOnUiThread(new Runnable() {
public void run() {
// reload content
PainLogTab.this.painLogListAdapter.notifyDataSetChanged();
if(painLogs.size() > 0){
getView().findViewById(android.R.id.empty).setVisibility(View.INVISIBLE);
}else{
getView().findViewById(android.R.id.empty).setVisibility(View.VISIBLE);
}
}
});
}
为了完成,getAll() 的主体及其附带的方法 getCursor():
public static Cursor getPainLogCursor() {
String[] columns = new String[] {
COLUMN_PAINLOG_ID,
COLUMN_PAINLOG_ENTRY,
COLUMN_PAINLOG_DATETIME
};
return getDatabase().query(PAINLOG_TABLE, columns, null, null, null, null,
null);
}
public static List<PainLog> getAllPainLogs() {
List<PainLog> painLogs = new ArrayList<PainLog>();
Cursor cursor = Database.getPainLogCursor();
if (cursor.moveToFirst()) {
while (cursor.moveToNext()) {
PainLog painLog = new PainLog();
painLog.setId(cursor.getInt(IDX_PAINLOG_ID));
painLog.setPainEntry(cursor.getString(IDX_PAINLOG_ENTRY));
painLog.setPainDateTime(cursor.getString(IDX_PAINLOG_DATETIME));
painLogs.add(painLog);
}
}
cursor.close();
return painLogs;
}
现在我可以通过一些代码来解释到目前为止我采取了哪些调试步骤。如上所述,当我查看数据库插入的 return 时,我得到一个非零的正数。但是,当我尝试在紧随其后的更新方法中打印日志数量时(没有删除或在途中调用任何东西),它显示 0,实际上,如果我跟随 Cursor,我发现它永远不会进入添加日志的循环到显示的列表,也表明它没有选择条目。
我曾尝试在事务中设置数据库插入,以便我可以手动提交,但这也无济于事。让我觉得更有趣的是,我在我的应用程序的其他地方有类似的功能,我保存用户首选项并将它们显示在列表中,这不会遇到同样的问题......我已经与这段代码进行了比较并且不能'找不到任何会导致它的差异。
总而言之,我的问题有两个:为什么只有我第一次插入空 table 时显示不存在,而后面的所有插入都很好?为什么我从数据库插入中获得了有效的 return,但当我查询丢失的数据时却立即跟随插入?
提前感谢您提供的任何帮助:)
if (cursor.moveToFirst()) { while (cursor.moveToNext()) {
这将跳过游标中的第一行。 moveToFirst()
移动到第一行,moveToNext()
移动到下一行,跳过第一行。
您可以将其替换为 while (cursor.moveToNext())
。当您从查询中获取游标时,它首先放置在索引 -1 处,即第一个之前的行。
if (cursor.moveToFirst()) {
while (cursor.moveToNext()) {
这将是最好的解决方案....