Моя проблема очень маленькая, но я не могу найти решение. Ниже мой код, и я объясню свою проблему.Сохранение «нет такой ошибки столбца» при использовании ListActivity с LoaderCallbacks
MetersActivity класс
public class MetersActivity extends ListActivity implements LoaderCallbacks<Cursor>{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.meters_list);
this.getListView().setDividerHeight(2);
fillData();
registerForContextMenu(getListView());
}
private void fillData() {
// Fields from the database (projection)
// Must include the _id column for the adapter to work
LoaderManager lm = getLoaderManager();
String[] dataColumns = {"_id ", " meterNumber " };
int[] meter = { R.id.meter_number_label};
adapter = new SimpleCursorAdapter(this, R.layout.meter_row,
null, dataColumns, meter, 0);
setListAdapter(adapter);
lm.initLoader(LOADER_ID, null, this);
}
@Override
public Loader<Cursor> onCreateLoader(int id,
Bundle args) {
String[] PROJECTION = new String[] { "_id ", " meterNumber "};
CursorLoader cursorLoader = new CursorLoader(MetersActivity.this,UserAccountsContentProvider.CONTENT_URI,PROJECTION, null, null, null);
return cursorLoader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// A switch-case is useful when dealing with multiple Loaders/IDs
switch (loader.getId()) {
case LOADER_ID:
// The asynchronous load is complete and the data
// is now available for use. Only now can we associate
// the queried Cursor with the SimpleCursorAdapter.
adapter.swapCursor(data);
break;
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// data is not available anymore, delete reference
adapter.swapCursor(null);
}
}
Мой класс, где я создаю свои таблицы:
// Database creation SQL statement for meters table
private static final String CREATE_TABLE_METERS = "create table "
+ TABLE_METERS
+ "("
+ METER_ID + " integer primary key autoincrement, "
+ METER_NUMBER + " integer not null, "
+ PLOT_NUMBER + " varchar not null, "
+ COLUMN_CATEGORY + " varchar not null "
+ ");";
// Database creation SQL statement for customers table
private static final String CREATE_TABLE_CUSTOMERS = "create table "
+ TABLE_CUSTOMERS
+ "("
+ KEY_CUSTOMER_ID + " integer primary key autoincrement, "
+ KEY_FIRST_NAME + " text, "
+ KEY_LAST_NAME + " text, "
+ KEY_ADDRESS + " varchar, "
+ KEY_EMAIL + " varchar, "
+ KEY_PHONE_NUMBER + " integer, "
+ KEY_ACCOUNT_NUMBER + " integer, "
+ KEY_METER_ID + " integer not null, "
+ KEY_METER_NUMBER + " integer not null, "
+ KEY_PLOT_NUMBER + " varchar not null, "
+" FOREIGN KEY ("+KEY_METER_ID+") REFERENCES "+TABLE_METERS+" ("+METER_ID+"), "
+" FOREIGN KEY ("+KEY_METER_NUMBER+") REFERENCES "+TABLE_METERS+" ("+METER_NUMBER+"), "
+" FOREIGN KEY ("+KEY_PLOT_NUMBER+") REFERENCES "+TABLE_METERS+" ("+PLOT_NUMBER+"));"
+ ");";
// Database creation SQL statement for water bills table
private static final String CREATE_TABLE_WATERBILL = "create table "
+ TABLE_WATER_BILL
+ "("
+ BILL_ID + " integer primary key autoincrement, "
+ BILL_NUMBER + " integer, "
+ KEY_BILLING_DATE + " date, "
+ KEY_PREVIOUS_READING + " integer, "
+ KEY_CURRENT_READING+ " integer, "
+ KEY_DATEOF_READING + " date, "
+ KEY_CONSUMPTION + " integer, "
+ KEY_DUE_DATE + " date, "
+ KEY_BILL_ITEMS + " varchar, "
+ KEY_RATE + " integer, "
+ KEY_CHARGES + " integer, "
+ KEY_CONSUMPTION_PERIOD + " date, "
+ KEY_TOTAL_DUE + " integer, "
+ BILL_METER_ID + " integer not null, "
+ " FOREIGN KEY ("+BILL_METER_ID+") REFERENCES "+TABLE_CUSTOMERS+" ("+KEY_METER_ID+"));"
+ ");";
public static void onCreate(SQLiteDatabase database){
database.execSQL(CREATE_TABLE_METERS);
database.execSQL(CREATE_TABLE_CUSTOMERS);
database.execSQL(CREATE_TABLE_WATERBILL);
}
Мой выход Logcat
03-13 10:45:29.058: E/SQLiteLog(827): (1) no such column: meterNumber
03-13 10:45:29.158: E/AndroidRuntime(827): FATAL EXCEPTION: AsyncTask #1
03-13 10:45:29.158: E/AndroidRuntime(827): java.lang.RuntimeException: An error occured while executing doInBackground()
03-13 10:45:29.158: E/AndroidRuntime(827): at android.os.AsyncTask$3.done(AsyncTask.java:299)
03-13 10:45:29.158: E/AndroidRuntime(827): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
03-13 10:45:29.158: E/AndroidRuntime(827): at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
03-13 10:45:29.158: E/AndroidRuntime(827): Caused by: android.database.sqlite.SQLiteException: no such column: meterNumber (code 1): , while compiling: SELECT _id , meterNumber FROM waterbills
03-13 10:45:29.158: E/AndroidRuntime(827): at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
Вопрос
Я пытаюсь получить данные из SQLite с помощью ContentProvider и отображать его как список. У меня есть активность списка, которая реализует LoaderCallbacks.I проверила тонны учебных пособий и даже следила за ними за буквой, но мое приложение падает по какой-то причине. У меня есть кнопки в основном действии с одним для отображения списка клиентов. Когда я нажимаю кнопку, я должен перейти к отдельной операции, которая показывает мне список имен, но вместо этого после нажатия кнопки с ошибкой «no this column while compiling ....».
У меня есть три стола - клиенты, счетчики и полигоны. Столбец meterNumber найден в табличных метрах, но я заметил, что в этой ошибке указано, что столбец «meterNumber» не найден в табличных waterbills! Так что я задаюсь вопросом, почему он ссылается на это в первую очередь, но я проверил код и, похоже, все в порядке. Я также удалил приложение по отдельности, увеличил версию базы данных, но до сих пор не работает. Иногда дополнительный набор глаз просто помогает увидеть то, что мы не делаем. Я действительно очень признателен за помощь.
Редактировать с классом провайдера контента
public class UserAccountsContentProvider extends ContentProvider{
private DatabaseHandler database;
// Used for the UriMacher
private static final int all_meters = 10;
private static final int single_meter = 20;
private static final int all_customers = 30;
private static final int single_customer = 40;
private static final int all_bills = 50;
private static final int single_bill = 60;
private static final String AUTHORITY = "com.isys.waterbillingsystem.contentprovider";
//table meters
private static final String METER_PATH = "meters";
public static final Uri CONTENT_URI_METER = Uri.parse("content://" + AUTHORITY
+ "/" + METER_PATH);
public static final String CONTENT_METER_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE
+ "/meters";
public static final String CONTENT_ITEM_METER_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE
+ "/meter";
//table customers
private static final String CUSTOMERS_PATH = "customers";
public static final Uri CONTENT_URI_CUSTOMERS = Uri.parse("content://" + AUTHORITY
+ "/" + CUSTOMERS_PATH);
public static final String CONTENT_CUSTOMER_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE
+ "/customers";
public static final String CONTENT_ITEM_CUSTOMER_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE
+ "/customer";
//table waterbills
private static final String BILL_PATH = "bills";
public static final Uri CONTENT_URI_WATERBILLS = Uri.parse("content://" + AUTHORITY
+ "/" + BILL_PATH);
private static final UriMatcher sURIMatcher = new UriMatcher(
UriMatcher.NO_MATCH);
static {
sURIMatcher.addURI(AUTHORITY, METER_PATH, all_meters);
sURIMatcher.addURI(AUTHORITY, METER_PATH + "/#", single_meter);
sURIMatcher.addURI(AUTHORITY, CUSTOMERS_PATH, all_customers);
sURIMatcher.addURI(AUTHORITY, CUSTOMERS_PATH + "/#", single_customer);
sURIMatcher.addURI(AUTHORITY, BILL_PATH, all_bills);
sURIMatcher.addURI(AUTHORITY, BILL_PATH + "/#", single_bill);
}
@Override
public boolean onCreate() {
try {
database = new DatabaseHandler(getContext());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = database.getWritableDatabase();
// Using SQLiteQueryBuilder instead of query() method
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(MeterTableDetails.TABLE_METERS);
queryBuilder.setTables(CustomerTableDetails.TABLE_CUSTOMERS);
queryBuilder.setTables(WaterBillTableDetails.TABLE_WATER_BILL);
int uriType = sURIMatcher.match(uri);
switch (uriType) {
case all_meters:
break;
case single_meter:
// Adding the ID to the original query
String id = uri.getPathSegments().get(1);
queryBuilder.appendWhere(MeterTableDetails.METER_ID + "=" + id);
break;
case all_customers:
break;
case single_customer:
// Adding the ID to the original query
String id1 = uri.getPathSegments().get(1);
queryBuilder.appendWhere(CustomerTableDetails.KEY_CUSTOMER_ID + "=" + id1);
break;
case all_bills:
break;
case single_bill:
// Adding the ID to the original query
String id2 = uri.getPathSegments().get(1);
queryBuilder.appendWhere(WaterBillTableDetails.BILL_ID + "=" + id2);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
Cursor cursor = queryBuilder.query(db, projection, selection,
selectionArgs, null, null, sortOrder);
// Make sure that potential listeners are getting notified
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
int uriType = sURIMatcher.match(uri);
SQLiteDatabase sqlDB = database.getWritableDatabase();
long id = 0;
switch (uriType) {
case all_meters:
id = sqlDB.insert(MeterTableDetails.TABLE_METERS, null, values);
break;
case all_customers:
id = sqlDB.insert(CustomerTableDetails.TABLE_CUSTOMERS, null, values);
break;
case all_bills:
id = sqlDB.insert(WaterBillTableDetails.TABLE_WATER_BILL, null, values);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return Uri.parse(METER_PATH + "/" + id);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int uriType = sURIMatcher.match(uri);
SQLiteDatabase db = database.getWritableDatabase();
switch (uriType) {
case all_meters:
break;
case single_meter:
String id = uri.getPathSegments().get(1);
selection = MeterTableDetails.METER_ID
+ "="
+ id
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
+ ')' : "");
break;
case all_customers:
break;
case single_customer:
String id1 = uri.getPathSegments().get(1);
selection = CustomerTableDetails.KEY_CUSTOMER_ID
+ "="
+ id1
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
+ ')' : "");
break;
case all_bills:
break;
case single_bill:
String id2 = uri.getPathSegments().get(1);
selection = WaterBillTableDetails.BILL_ID
+ "="
+ id2
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
+ ')' : "");
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
int deleteCount;
deleteCount = db.delete(MeterTableDetails.TABLE_METERS, selection,
selectionArgs);
deleteCount = db.delete(CustomerTableDetails.TABLE_CUSTOMERS, selection,
selectionArgs);
deleteCount = db.delete(WaterBillTableDetails.TABLE_WATER_BILL, selection,
selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return deleteCount;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int uriType = sURIMatcher.match(uri);
SQLiteDatabase db = database.getWritableDatabase();
switch (uriType) {
case all_meters:
break;
case single_meter:
String id = uri.getPathSegments().get(1);
selection = MeterTableDetails.METER_ID
+ "="
+ id
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
+ ')' : "");
break;
case all_customers:
break;
case single_customer:
String id1 = uri.getPathSegments().get(1);
selection = CustomerTableDetails.KEY_CUSTOMER_ID
+ "="
+ id1
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
+ ')' : "");
break;
case all_bills:
break;
case single_bill:
String id2 = uri.getPathSegments().get(1);
selection = WaterBillTableDetails.BILL_ID
+ "="
+ id2
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
+ ')' : "");
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
int updateCount;
updateCount = db.update(MeterTableDetails.TABLE_METERS, values,
selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
updateCount = db.update(CustomerTableDetails.TABLE_CUSTOMERS, values, selection,
selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
updateCount = db.update(WaterBillTableDetails.TABLE_WATER_BILL, values, selection,
selectionArgs);
return updateCount;
}
}
Почему у вас есть пробелы вокруг имен ваших колонок? – pskink
Если я правильно понял вашу проблему, похоже, у вас что-то запуталось в вашем Content Provider. Отправьте соответствующий код из этого класса. –
@pskink, потому что от других людей на этом сайте, у которых была аналогичная проблема «без такого столбца», некоторым было рекомендовано создавать пробелы после запятой, чтобы запрос не интерпретировал его как одно слово после знака плюс ... я решил попробовать это также ... но, очевидно, это не решение моей проблемы. – naffie