SlandShow
@SlandShow
70% of my body is made of movies.

Почему происходит шибка при создании БД (SQLite)в Android приложении?

Доброго времени суток.

Никак не могу обнаружить причину проблемы, а конкретнее:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test_apps.slandshow.controlyourcash/com.test_apps.slandshow.controlyourcash.view.CashSettingsActivity}: android.database.sqlite.SQLiteException: Can't downgrade database from version 2 to 1
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
aused by: android.database.sqlite.SQLiteException: Can't downgrade database from version 2 to 1
                      at android.database.sqlite.SQLiteOpenHelper.onDowngrade(SQLiteOpenHelper.java:360)
                      at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:254)
                      at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
                      at com.test_apps.slandshow.controlyourcash.model.CashDBHandler.getAllProducts(CashDBHandler.java:47)
                      at com.test_apps.slandshow.controlyourcash.view.CashSettingsActivity.displayProductList(CashSettingsActivity.java:129)
                      at com.test_apps.slandshow.controlyourcash.view.CashSettingsActivity.onCreate(CashSettingsActivity.java:55)

UPDATE: Поменял версию на 2, но возникла проблема с другим:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test_apps.slandshow.controlyourcash/com.test_apps.slandshow.controlyourcash.view.CashSettingsActivity}: android.database.sqlite.SQLiteException: no such column: income (code 1): , while compiling: SELECT _id, productname, coast, income FROM products


У меня есть класс CashSettingsActivity, который манипулирует классом CashDBHandler.

Вот сокращённый код класса CashDBHandler (некоторые методы опущены для читабельности):
public class CashDBHandler extends SQLiteOpenHelper {

    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "productDB.db";
    public static final String TABLE_PRODUCTS = "products";
    public static final String COLUMN_ID = "_id";
    public static final String COLUMN_PRODUCTNAME = "productname";
    public static final String COLUMN_INCOME = "income";
    public static final String COLUMN_COAST = "coast";

 public CashDBHandler(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, DATABASE_NAME, factory, DATABASE_VERSION);
    }


    @Override
    public void onCreate(SQLiteDatabase db) {
        String create_products_table = "CREATE TABLE " + TABLE_PRODUCTS + " (" +
                COLUMN_ID + " INTEGER PRIMARY KEY, " + COLUMN_PRODUCTNAME + " TEXT," +
                COLUMN_COAST + " INTEGER, " + COLUMN_INCOME + "INTEGER)";
        db.execSQL(create_products_table);

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_PRODUCTS);
        onCreate(db);
    }

// Ошибка!
public Cursor getAllProducts() {
        SQLiteDatabase db = this.getReadableDatabase(); 
        Cursor cursor = db.query(TABLE_PRODUCTS, new String[]{COLUMN_ID, COLUMN_PRODUCTNAME,
                COLUMN_COAST, COLUMN_INCOME}, null, null, null, null, null); // Ошибка!
        if (cursor != null) {
            cursor.moveToFirst();
            return cursor;
        } else {
            return null;
        }
    }


 public void addProduct(Cash product) {
        ContentValues values = new ContentValues();
        values.put(COLUMN_PRODUCTNAME, product.getName());
        values.put(COLUMN_COAST, product.getCoast());
        values.put(COLUMN_INCOME, product.getIncome());
        SQLiteDatabase db = this.getWritableDatabase(); 
        db.insert(TABLE_PRODUCTS, null, values);
        db.close();
    }
 ...
}


А вот краткое описание класса CashSettingsActivity:
public class CashSettingsActivity extends AppCompatActivity {

    private CashDBHandler dbHandler;
    private SimpleCursorAdapter simpleCursorAdapter;
    private TextView idView;
    private EditText etName;
    private EditText etCoast;
    private EditText etIncome;
    private ListView lvProducts;
    private HashMap<Long, String> map;

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.cash_database);
        idView = (TextView) findViewById(R.id.tvID);
        etName = (EditText) findViewById(R.id.etName);
        etCoast = (EditText) findViewById(R.id.etCoast);
        etIncome = (EditText) findViewById(R.id.etIncome);
        lvProducts = (ListView) findViewById(R.id.productList);
        dbHandler = new CashDBHandler(this, null, null, 1);

        displayProductList();
        setHandler(lvProducts);

    }

    public void newProduct(View v) {
            Cash p = new Cash(etName.getText().toString(),
                    Integer.parseInt(etCoast.getText().toString()),
                    Integer.parseInt(etIncome.getText().toString()));
            dbHandler.addProduct(p);
            idView.setText("Record Added!");
            etName.setText("");
            etCoast.setText("");
            etIncome.setText("");
            displayProductList();
    }

// Ошибка!
 private void displayProductList() {
            Cursor cursor = dbHandler.getAllProducts(); // Тут происходит ошибка!
            if (cursor == null) {
                idView.setText("Unable to generate cursor.");
                return;
            }
            if (cursor.getCount() == 0) {
                idView.setText("No Products in the Database.");
                return;
            }
            String[] columns = new String[]{
                    CashDBHandler.COLUMN_ID,
                    CashDBHandler.COLUMN_PRODUCTNAME,
                    CashDBHandler.COLUMN_COAST,
                    CashDBHandler.COLUMN_INCOME
            };
            int[] boundTo = new int[]{
                    R.id.pId,
                    R.id.pName,
                    R.id.pCoast,
                    R.id.pIncome
            };
            simpleCursorAdapter = new SimpleCursorAdapter(this,
                    R.layout.activity_cash_settings,
                    cursor,
                    columns,
                    boundTo,
                    0);
            lvProducts.setAdapter(simpleCursorAdapter);
    }
...


Таким образом, при исполнении инструкции: SQLiteDatabase db = this.getReadableDatabase();
Вылетает исключение, благодаря которому я не могу создать таблицу.

Никак не могу понять, что же я делаю не так?
  • Вопрос задан
  • 1004 просмотра
Решения вопроса 1
SlandShow
@SlandShow Автор вопроса
70% of my body is made of movies.
В общем-то проблема была в моей криворукости.

При создании таблицы я написал вот это:
String create_products_table = "CREATE TABLE " + TABLE_PRODUCTS + " (" +
                COLUMN_ID + " INTEGER PRIMARY KEY, " + COLUMN_PRODUCTNAME + " TEXT," +
                COLUMN_COAST + " INTEGER, " + COLUMN_INCOME + "INTEGER)";


И я сам не заметил, но на выходе получил не совсем то, что нужно:
CREATE TABLE products (_id INTEGER PRIMARY KEY, productname TEXT, coast INTEGER, incomeInteger TEXT);


Т.е я забыл поставить пробел между COLUMN_INCOME и "INTEGER); и SQLite автоматически определил это как текст.

126cd13f0c4d46369b67602b96f9cc1e.png
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
a13xsus
@a13xsus
Lazy developer
private static final int DATABASE_VERSION = 1;

> Can't downgrade database from version 2 to 1

У устройства версия 2, ты пытаешься ему подсунуть 1.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы