2014-03-13 2 views
0

Моя проблема очень маленькая, но я не могу найти решение. Ниже мой код, и я объясню свою проблему.Сохранение «нет такой ошибки столбца» при использовании 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; 
    } 


} 
+2

Почему у вас есть пробелы вокруг имен ваших колонок? – pskink

+0

Если я правильно понял вашу проблему, похоже, у вас что-то запуталось в вашем Content Provider. Отправьте соответствующий код из этого класса. –

+0

@pskink, потому что от других людей на этом сайте, у которых была аналогичная проблема «без такого столбца», некоторым было рекомендовано создавать пробелы после запятой, чтобы запрос не интерпретировал его как одно слово после знака плюс ... я решил попробовать это также ... но, очевидно, это не решение моей проблемы. – naffie

ответ

1

Так у вас нет MeterNumber столбца в таблице waterbills:

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+"));" 
+ ");"; 

Что вы ждете от запроса?

В поставщике данных установить таблицы, которые будут использоваться в запросе так:

queryBuilder.setTables(MeterTableDetails.TABLE_METERS); 

queryBuilder.setTables(CustomerTableDetails.TABLE_CUSTOMERS); 

queryBuilder.setTables(WaterBillTableDetails.TABLE_WATER_BILL); 

Это неправильно. Запрос будет исключен только в таблице WATER_BILL. Если вы хотите получить данные из многих таблиц use JOIN:

queryBuilder.setTables(MeterTableDetails.TABLE_METERS INNER JOIN CustomerTableDetails.TABLE_CUSTOMERS ON (....)); 
+0

Эй, @ MikkanRin нет, у меня нет этой колонки в таблице счетов за воду. Запрос должен дать мне список всех номеров счетчиков, зарегистрированных в таблице счетчиков. ,поэтому в onCreate Loader я вхожу в столбцы «_id» и «meterNumber» ... – naffie

+0

Итак, почему вы используете таблицу водяных знаков, чтобы получить MeterNumbers? '03-13 10: 45: 29.158: E/AndroidRuntime (827): Caused by: android.database.sqlite.SQLiteException: нет такого столбца: meterNumber (код 1): при компиляции: SELECT _id, meterNumber FROM waterbills' – MikkaRin

+0

Я не ... это проблема ... или, по крайней мере, если я ... тогда я не могу найти, где именно в моем коде, я использовал waterbills, чтобы получить meterNumber .. вы можете определить, где я это делаю в своем коде? ... – naffie

Смежные вопросы