Метод onCreate() SQLiteHelper никогда не вызывается

Я создаю базу данных в Android с помощью SQLite.

Я написал свой код для создания таблицы с именем products в методе onCreate().

Затем, когда я вызываю метод add() для добавления некоторых значений в таблицу, я получаю сообщение об ошибке, что такой таблицы с именем products не существует.

Вот мой класс SQLiteHelper:

public class MySQLiteHelper extends SQLiteOpenHelper {

    //variable declarations and some code
    ...

    @Override
    public void onCreate(SQLiteDatabase db) {

        // SQL statement to create a products table
        String CREATE_PRODUCTS_TABLE = "CREATE TABLE "+TABLE_NAME+ " ( " +
                "id INTEGER PRIMARY KEY AUTOINCREMENT, " +
                "url TEXT, " +
                "title TEXT, " +
                "price INTEGER );";

        // create products table
        db.execSQL(CREATE_PRODUCTS_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Drop older table if existed
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);

        // Create tables again
        onCreate(db);
    }


void add(String url, String title, String price) {


    this.url = url;
    this.title = title;
    this.price = price;

    // 1. get reference to writable DB
    SQLiteDatabase db = this.getWritableDatabase();

    // 2. create ContentValues to add key "column"/value
    ContentValues values = new ContentValues();
    values.put(KEY_URL, url);
    values.put(KEY_TITLE, title);
    values.put(KEY_PRICE, price);

    // 3. insert
    db.insert(TABLE_NAME, // table
            null, //nullColumnHack
            values); // key/value -> keys = column names/ values = column values

    // 4. close
    db.close();
}

Из аналогичного вопроса я прочитал, что onCreate() не является конструктором и вызывается только тогда, когда база данных не существует, но в моем случае база данных тоже не существует, так почему она не вызывается?

Я также узнал, что нам нужно позвонить getWritableDatabase() или getReadableDatabase()

Но я не уверен, где сделать такой вызов в моем коде.

Я попытался поместить «код создания таблицы», который находится в onCreate(), в моем методе add(). При первом запуске я ничего не получил, но в следующий раз я продолжаю получать сообщение об ошибке, что «таблица уже существует».

Теперь, как я могу убедиться, что таблица создана правильно только один раз, прежде чем я вызову свой метод add() для вставки некоторых значений. Любая помощь, пожалуйста?

ИЗМЕНИТЬ:

Мой Logcat читает:

03-07 00:59:22.684    2107-2147/com.example.nikhil.amazon1 W/EGL_emulation﹕ eglSurfaceAttrib not implemented
03-07 00:59:22.684    2107-2147/com.example.nikhil.amazon1 W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xa5683060, error=EGL_SUCCESS
03-07 00:59:24.922    2107-2120/com.example.nikhil.amazon1 I/art﹕ Background sticky concurrent mark sweep GC freed 1464(89KB) AllocSpace objects, 7(2MB) LOS objects, 7% free, 9MB/9MB, paused 75.596ms total 203.616ms
03-07 00:59:25.338    2107-2413/com.example.nikhil.amazon1 E/SQLiteLog﹕ (1) no such table: products
03-07 00:59:25.339    2107-2413/com.example.nikhil.amazon1 E/SQLiteDatabase﹕ Error inserting price=   24,599.00 title=Google Nexus 5 D821 (16GB, Black) url=http://www.amazon.in/Google-Nexus-D821-16GB-Black/dp/B00GC1J55C/ref=sr_1_1?s=electronics&ie=UTF8&qid=1421161258&sr=1-1&keywords=Google
    android.database.sqlite.SQLiteException: no such table: products (code 1): , while compiling: INSERT INTO products(price,title,url) VALUES (?,?,?)
            at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
            at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
            at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
            at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
            at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
            at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
            at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1469)
            at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1341)
            at com.example.nikhil.amazon1.MySQLiteHelper.add(MySQLiteHelper.java:86)
            at com.example.nikhil.amazon1.FirstParsing$1.run(FirstParsing.java:71)
            at java.lang.Thread.run(Thread.java:818)

Моя проблема точно такая же, как: 1) Android SQLiteOpenHelper: метод onCreate() не называется. Почему?

2) SQLiteOpenHelper не может вызвать onCreate?

3) SQLiteOpenHelper onCreate не вызывается? (БД не существует)

Но мне трудно понять это и применить к моему коду.


person Nikhil    schedule 06.03.2015    source источник
comment
Ваш код говорит "CREATE TABLE TABLE_NAME ( ". Разве не должно быть написано "CREATE TABLE "+TABLE_NAME+" ( "?   -  person antonio    schedule 06.03.2015
comment
Ой! На самом деле у меня есть переменная с именем TABLE_NAME. Я не помещал сюда весь свой код, чтобы избежать сложности.   -  person Nikhil    schedule 06.03.2015
comment
Да, но ваш код создает таблицу с именем TABLE_NAME, а не продукты   -  person antonio    schedule 06.03.2015
comment
В моем коде есть `private static final String TABLE_NAME = products;`.   -  person Nikhil    schedule 06.03.2015
comment
Кажется, я не объясняю или не понимаю вас, извините... Я имею в виду, что "CREATE TABLE TABLE_NAME ( " создает таблицу с именем TABLE_NAME. Ваш код должен быть "CREATE TABLE "+TABLE_NAME+" ( "для использования вашего private static final String TABLE_NAME = "products";   -  person antonio    schedule 06.03.2015
comment
Ага, спасибо, что указали. Я изменил это. Но я все еще получаю ту же ошибку :)   -  person Nikhil    schedule 06.03.2015
comment
Я предполагаю, что файл базы данных все еще существует, и в настоящее время он имеет код версии 1, а это означает, что ваш метод onUpgrade никогда не будет вызван, поскольку база данных уже является последней версией. Удалить файл базы данных. Вы можете сделать это, удалив приложение на своем устройстве или очистив хранилище вашего приложения. Вы также можете увеличить код версии БД. Однако ваш обновленный код создания таблицы теперь имеет синтаксическую ошибку. В конец строки "CREATE TABLE" нужно добавить пробел, иначе результирующий код SQL будет иметь вид: CREATE TABLEproducts....   -  person tiguchi    schedule 06.03.2015
comment
Я согласен с @NobuGames. Зайдите в настройки приложения в эмуляторе/телефоне и удалите кеш и все данные. После повторного запуска вашего проекта. Если вы изменили свой код и запустили его позже, ваша версия БД по-прежнему останется 1, и она не будет создана снова!   -  person Giorgio Antonioli    schedule 06.03.2015
comment
Спасибо за ваш вклад. Пробовал. Но тот же результат. В первом случае к моменту вызова метода add() таблица не создается. Я обновлю свой вопрос своим отчетом logcat.   -  person Nikhil    schedule 06.03.2015
comment
Моя проблема точно такая же, как: stackoverflow.com/questions/6791852/ и stackoverflow.com/questions/10147888/ Но я не смог применить то же самое к своему приложению. Может ли кто-нибудь помочь с этим, пожалуйста. Спасибо за ваше время.   -  person Nikhil    schedule 06.03.2015


Ответы (1)


Это может помочь в дальнейшей разработке

MySQLiteHelper — определяет базу данных, таблицы и т. д.

public class MySQLiteHelper extends SQLiteOpenHelper {

    private static final String FILE_NAME = "application.db";
    private static final int DB_VERSION = 1;
    private final String TAG = MySQLiteHelper.class.getCanonicalName();
    private static SQLiteDatabase database = null;

    public MySQLiteHelper(Context context) {
        super(context, FILE_NAME, null, DB_VERSION);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // TODO Auto-generated method stub
        //version 1
        database.execSQL(ProductsTbl.CREATE_SQL);
        //can create new tables if necessary, make sure to increase database version

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO Auto-generated method stub
        Log.i(TAG, "Upgrading from version " + oldVersion + " to version "
                                + newVersion);
        for (int i = oldVersion + 1; i <= newVersion; i++) {
            Log.i(TAG, "version is becoming current " + i);
            switch (i) {
                case 2:
                    db.execSQL(ProductsTbl.CREATE_SQL);
                    break;
            //add more cases for each additional table added

            }
        }
    }

    public static class ProductsTbl {
        public static final String TABLE_NAME = "products";
        public static final String ID = "_id";
        public static final String URL = "url";
        public static final String TITLE = "title";
        public static final String PRICE = "price";
        public static final String[] TABLE_COLUMNS = { ID, URL, TITLE, PRICE };
        public static final String CREATE_SQL = "create table " + TABLE_NAME
                                                                                        + "(" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
                                                                                        + URL + " TEXT,"
                                                                                        + TITLE + " TEXT,"
                                                                                        + PRICE + " INTEGER);";
    }

}

MySQLiteDatasource — определяет методы доступа, вставки, удаления и т. д.

public class MySQLiteDatasource {

    //Database fields
    private SQLiteDatabase database;
    private MySQLiteHelper dbHelper;

    public MySQLiteDatasource(Context context) {
        dbHelper = new MySQLiteHelper(context);
    }

    public void open() throws SQLException {
        database = dbHelper.getWritableDatabase();
    }

    public void close() {
        dbHelper.close();
    }

    public void insertProduct(String url, String title, String price) {
        ContentValues values = new ContentValues();
        values.put(MySQLiteHelper.ProductsTbl.URL, url);
        values.put(MySQLiteHelper.ProductsTbl.TITLE, title);
        values.put(MySQLiteHelper.ProductsTbl.PRICE, price);

        try {
            database.insertOrThrow(MySQLiteHelper.ProductsTbl.TABLE_NAME, null, values);
        } catch (SQLiteConstraintException e) {
            //System.out.println(e);
            Log.e("SQLite Database", "Unable to INSERT into Database, possible duplicate topic already exists.");
        }
    }

}

Вот как вы можете использовать 2 класса внутри активности или чего-то подобного.

  public static void addProductToDB(String url, String title, String price) {
    MySQLiteDatasource datasource = new MySQLiteDatasource(this);
    datasource.open();
    datasource.insertProduct(url, title, price);
    datasource.close();
  }

Вы также можете захотеть изучить определение объекта Product для хранения данных, полученных из базы данных на более позднем этапе.

person Coova    schedule 06.03.2015
comment
Спасибо! Я изменил это. Но все тот же результат. :) - person Nikhil; 06.03.2015
comment
Вы пытались зайти в диспетчер приложений и принудительно остановить/очистить данные/очистить кеш и попробовать повторно открыть приложение? - person Coova; 06.03.2015
comment
Можете ли вы опубликовать свой оператор INSERT? - person Coova; 06.03.2015
comment
Я обновил свой метод add() в вопросе. Я получаю сообщение об ошибке прямо в операторе вставки, что таблица с именем products не существует. - person Nikhil; 06.03.2015
comment
Я чувствую, что хотя вызывается метод add(), код в onCreate(), который создает таблицу, не вызывается. - person Nikhil; 06.03.2015
comment
Я посмотрю на это. Я думаю, вам следует изменить структуру использования базы данных. Я собираюсь опубликовать часть обновленного кода. - person Coova; 06.03.2015
comment
Проверьте обновленный код и дайте мне знать, если у вас возникнут другие проблемы. - person Coova; 06.03.2015