嘿家伙我一直在这个问题上困住了很长一段时间,但我似乎无法解决它。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