嘿傢伙我一直在這個問題上困住了很長一段時間,但我似乎無法解決它。Android SQLite查詢與哪裏不工作
我嘗試從我的Android應用程序中的SQLite數據庫查詢一行,我有一些奇怪的行爲。
我有以下的單元測試:
public class DatabaseTest extends AndroidTestCase {
...
public void testSaveMeeting() {
Meeting meeting = new Meeting(1, MeetingStatus.ONGOING);
MeetingDataSource mds = new MeetingDataSource(getContext());
long meetingId = mds.save(meeting);
assertEquals(meeting, mds.getById(meetingId));
}
}
在這裏,我嘗試我的模型對象meeting
保存到數據庫中與我的數據庫映射。下面的代碼片段是我的模型Meeting
存儲應保存到數據庫中的數據:
public class Meeting {
private long id;
private MeetingStatus meetingStatus;
public Meeting() {}
public Meeting(long meetingId, MeetingStatus meetingStatus) {
this.id = meetingId;
this.meetingStatus = meetingStatus;
}
public long getId() { return id; }
public void setId(long id) { this.id = id; }
public void setMeetingStatus(MeetingStatus meetingStatus) { this.meetingStatus = meetingStatus; }
public MeetingStatus getMeetingStatus() { return meetingStatus; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Meeting meeting = (Meeting) o;
return id == meeting.id && meetingStatus == meeting.meetingStatus;
}
@Override
public int hashCode() {...}
}
而且我MeetingDataSource是一個映射器類,我試圖映射我的模型對象到數據庫中,反之亦然。該類如下所示:
public class MeetingDataSource extends DataSource<Meeting> {
private static String REQUEST_TABLE_NAME = DatabaseContract.MeetingTable.TABLE_NAME;
private static String[] ALL_COLUMNS = {
DatabaseContract.MeetingTable._ID,
DatabaseContract.MeetingTable.COLUMN_NAME_STATUS
};
public MeetingDataSource(Context context) { super(context); }
@Override
public Meeting cursorToObject(Cursor cursor) {
if(cursor != null && cursor.moveToFirst()) {
Meeting meeting = new Meeting();
meeting.setId(cursor.getLong(0));
meeting.setMeetingStatus(MeetingStatus.valueOfLabel(cursor.getString(1)));
return meeting;
}
return null;
}
@Override
protected ContentValues objectToContentValues(Meeting meeting) {
ContentValues values = new ContentValues();
values.put(DatabaseContract.MeetingTable._ID, meeting.getId());
values.put(DatabaseContract.MeetingTable.COLUMN_NAME_STATUS, meeting.getMeetingStatus().getLabel());
return values;
}
@Override
public Meeting getById(long id) {
try {
openReadConnection();
} catch (SQLException e) {
e.printStackTrace();
}
String where = DatabaseContract.MeetingTable._ID + " = ?";
String[] whereValues = { String.valueOf(id) };
// I think this is the part where my Problem is.
Cursor cursor = database.query(
REQUEST_TABLE_NAME,
ALL_COLUMNS,
where,
whereValues,
null,
null,
null);
Meeting meeting = cursorToObject(cursor);
closeConnection();
return meeting;
}
@Override
public long save(Meeting meeting) {
try {
openWriteConnection();
} catch (SQLException e) {
e.printStackTrace();
}
long rowId = database.insert(REQUEST_TABLE_NAME, null, objectToContentValues(meeting));
closeConnection();
return rowId;
}
@Override
public void update(Meeting meeting) {...}
@Override
public List<Meeting> getAll() {...}
}
此類擴展以下適配器DataSource
。這是SQLiteOpenHelper
一個包裝物,用於創建數據庫本身:
public abstract class DataSource<DatabaseTableType> {
protected Context context;
protected SQLiteDatabase database;
private DatabaseHelper dbHelper;
public DataSource(Context context) {
this.context = context;
dbHelper = new DatabaseHelper(context);
}
protected void openReadConnection() throws SQLException {
database = dbHelper.getReadableDatabase();
}
protected void openWriteConnection() throws SQLException { database = dbHelper.getWritableDatabase(); }
protected void closeConnection() {
dbHelper.close();
}
protected abstract DatabaseTableType cursorToObject(Cursor cursor);
protected abstract ContentValues objectToContentValues(DatabaseTableType object);
public abstract DatabaseTableType getById(long id);
public abstract List<DatabaseTableType> getAll();
public abstract long save(DatabaseTableType object);
public abstract void update(DatabaseTableType object);
}
現在這裏是奇數部分: 當我加入其中的方法getById
像上面我的assertEquals聲明和論點在我MeetingDataSource
在測試中失敗了,因爲我的光標是空的,所以的cursorToObject
返回值,但如果我離開它,就像這樣:
Cursor cursor = database.query(
REQUEST_TABLE_NAME,
ALL_COLUMNS,
null,
null,
null,
null,
null);
我的測試suceeds,這使我相信,正確的對象已經產生通過cursorToObject
。 我也試過rawQuery
:
Cursor cursor = database.rawQuery("SELECT * FROM " + REQUEST_TABLE_NAME + " WHERE _id = ?", whereValues);
返回也null
。而
Cursor cursor = database.rawQuery("SELECT * FROM " + REQUEST_TABLE_NAME, null);
返回正確的Meeting
並且還讓我的測試通過。
我非常感謝任何答案:)
編輯1
這migth是有幫助的,看我如何定義我的表,什麼我SQLiteOpenHelper
一樣。
這裏是我的DatabaseHelper延伸SQLiteOpenHelper
創造和推倒我的數據庫時,它的首次訪問的:
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "DatabaseHelper";
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "lma.db";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DatabaseContract.AttendanceStatusTable.SETUP_TABLE);
db.execSQL(DatabaseContract.MeetingStatusTable.SETUP_TABLE);
db.execSQL(DatabaseContract.MeetingTable.CREATE_TABLE);
db.execSQL(DatabaseContract.AttendanceTable.CREATE_TABLE);
db.execSQL(DatabaseContract.LocationTable.CREATE_TABLE);
db.execSQL(DatabaseContract.ContactPositionTable.CREATE_TABLE);
db.execSQL(DatabaseContract.RouteTable.CREATE_TABLE);
db.execSQL(DatabaseContract.StepTable.CREATE_TABLE);
db.execSQL(DatabaseContract.WarningTable.CREATE_TABLE);
db.execSQL(DatabaseContract.RoutesToWarningsTable.CREATE_TABLE);
db.execSQL(DatabaseContract.RoutesToStepsTable.CREATE_TABLE);
Log.i(TAG, "Database created");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(DatabaseContract.RoutesToStepsTable.DROP_TABLE);
db.execSQL(DatabaseContract.RoutesToWarningsTable.DROP_TABLE);
db.execSQL(DatabaseContract.WarningTable.DROP_TABLE);
db.execSQL(DatabaseContract.StepTable.DROP_TABLE);
db.execSQL(DatabaseContract.RouteTable.DROP_TABLE);
db.execSQL(DatabaseContract.ContactPositionTable.DROP_TABLE);
db.execSQL(DatabaseContract.LocationTable.DROP_TABLE);
db.execSQL(DatabaseContract.AttendanceTable.DROP_TABLE);
db.execSQL(DatabaseContract.MeetingTable.DROP_TABLE);
db.execSQL(DatabaseContract.MeetingStatusTable.DROP_TABLE);
db.execSQL(DatabaseContract.AttendanceStatusTable.DROP_TABLE);
Log.i(TAG, "Database dropped");
onCreate(db);
}
}
在我DatabaseContract我定義所有的SQL語句來創建我的表。它還定義了我的列名和表名:
public final class DatabaseContract {
private static final String INT_TYPE = " INTEGER";
private static final String VARCHAR_TYPE = " VARCHAR(25)";
private static final String COMMA = ", ";
private static final String DROP_TABLE_STATEMENT = "DROP TABLE IF EXISTS ";
private static final String PRIMARY_KEY = " PRIMARY KEY";
private static final String NOT_NULL = " NOT NULL";
// To prevent someone from accidentally instantiating the contract class
public DatabaseContract() {}
// Enum Types
...
public static abstract class MeetingStatusTable implements BaseColumns {
public static final String TABLE_NAME = "meeting_statuses";
public static final String COLUMN_NAME_TYPE = "type";
public static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + COLUMN_NAME_TYPE + VARCHAR_TYPE + PRIMARY_KEY + ");";
public static final String INSERT_DATA = "INSERT INTO " + TABLE_NAME + "(" + COLUMN_NAME_TYPE + ") " + "VALUES (\"NEW\"), (\"ONGOING\"), (\"TERMINATED\"), (\"COMPLETED\");";
public static final String SETUP_TABLE = CREATE_TABLE + INSERT_DATA;
public static final String DROP_TABLE = DROP_TABLE_STATEMENT + TABLE_NAME + ";";
}
// Data Tables
public static abstract class MeetingTable implements BaseColumns {
public static final String TABLE_NAME = "meetings";
public static final String COLUMN_NAME_STATUS = "status";
public static final String CREATE_TABLE =
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
_ID + INT_TYPE + PRIMARY_KEY + NOT_NULL + COMMA +
COLUMN_NAME_STATUS + VARCHAR_TYPE + NOT_NULL + COMMA +
" FOREIGN KEY (" + COLUMN_NAME_STATUS + ") REFERENCES " + MeetingStatusTable.TABLE_NAME + " (" + MeetingStatusTable.COLUMN_NAME_TYPE + ")" +
");";
public static final String DROP_TABLE = DROP_TABLE_STATEMENT + TABLE_NAME + ";";
}
...
}
EDIT 2
那麼在評論中我得到了我的要求,我MeetingDataSource
save
方法實際上是否返回正確的值,這是不案件。通過編輯,我在我的MeetingDataSource
中添加了我的保存方法的代碼,這似乎是一個實際的麻煩製造者。
表的定義? 'save'返回的實際值是多少? –
@CL。我編輯我的郵政表格定義。那麼這是一個很好的問題,實際上我會檢查一個額外的斷言。 – TehQuila
@CL。似乎有問題:當我在我的代碼中有以下斷言:assertEquals(meeting.getId(),meetingId);我得到:'AssertionFailedError:expected:<1>但是:<-1>'我也會發布我的save方法的代碼。 – TehQuila