0

SQLite テーブルにいくつかのレコードを追加しようとしていますが、LogCat からテーブルが存在しないと表示されます。そしてDDMSは、はい、そのテーブルが作成されていない/作成されていないことを示しています。

それでも、SQLiteOpenHelper クラスでテーブルを作成します。

public class SQLiteHandlerDeliveryItem extends SQLiteOpenHelper {
    . . .
    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        String CREATE_DELIVERYITEMS_TABLE = "CREATE TABLE " +
                TABLE_DELIVERYITEMS + "("
                + COLUMN_ID + " INTEGER PRIMARY KEY," + COLUMN_INVOICENUM + " TEXT,"
                + COLUMN_UPCPLU + " TEXT," + COLUMN_VENDORITEMID + " TEXT,"
                + COLUMN_PACKSIZE + " INTEGER," + COLUMN_DESCRIPTION + " TEXT,"
                //+ COLUMN_COST + " REAL,"  + COLUMN_MARGIN + " REAL," + COLUMN_LISTPRICE + " REAL,"
                + COLUMN_COST + " REAL DEFAULT 0,"  + COLUMN_MARGIN + " REAL DEFAULT 0," + 

COLUMN_LISTPRICE + " REAL DEFAULT 0,"
                + COLUMN_DEPTNUM + " INTEGER," + COLUMN_SUBDEPT + " TEXT," + COLUMN_QTY + " TEXT"
                + ")";
        sqLiteDatabase.execSQL(CREATE_DELIVERYITEMS_TABLE);
    }

レコードを追加するクラスのメソッドを呼び出します。

SQLiteHandlerDeliveryItem sqliteHandler = new SQLiteHandlerDeliveryItem(SQLiteActivity.this, null);
sqliteHandler.addDeliveryItem(delItem);

これは SQLiteHandlerDeliveryItem のコンストラクターを呼び出す必要があります (sqliteHandler がインスタンス化されている場合) が、そうではありません! onCreate() メソッドにブレークポイントを設定しましたが、確かに到達していません。

なんで?テーブルが作成されるように、コンストラクターを強制的に呼び出すにはどうすればよいですか?

奇妙なのは、他の (動作中の) SQLiteOpenHelper クラスにもブレークポイントを設定したことです。テーブルが存在する/そのコードから作成されたため、少なくとも1回は機能しました。

だから、私のスイングには明らかに穴があります。私は何を誤解しているか間違っていますか?

アップデート

私は答えをTHE答えとしてマークしました。

に関して:

「1. ある時点で getWritableDatabase() または getReadableDatabase() を呼び出す必要があります。」

次のように、レコードを作成または読み取る各メソッドで getWritableDatabase() を呼び出します

public long addDeliveryItem(DeliveryItem delItem) {
    long IdAdded = 0;
    ContentValues values = new ContentValues();
    values.put(COLUMN_INVOICENUM, delItem.get_invoiceNumber());
    . . .
    values.put(COLUMN_QTY, delItem.get_quantity());

    SQLiteDatabase db = this.getWritableDatabase(); <= Rot Cheer

    if (db != null) {
        IdAdded = db.insert(TABLE_DELIVERYITEMS, null, values);
    }
    . . .

...そして、に関して:

「2. SQLiteHandlerDeliveryItem のコンストラクターでは、super(...) を呼び出す必要があります。」

SQLiteOpenHelper を拡張するクラスで super を呼び出します

public SQLiteHandlerDeliveryItem(Context context, SQLiteDatabase.CursorFactory factory)     
{
    super(context, DATABASE_NAME, factory, DATABASE_VERSION);
}

だから...私はまだ問題/解決策が何であるかわかりません...

更新 2

したがって、LogCat でこのテーブルにレコードを挿入しようとすると、次のようになります。

E/SQLiteLog﹕ (1) no such table: deliveryitems

それでも、レコードを追加しようとする私のコードは、次のように SQLiteOpenHelper を拡張する対応する/適切なクラスをインスタンス化します。

else if ("Delivery Items".equals(tableName)) {
    try {
        JSONArray jsonArr = new JSONArray(result);
        for (int i = 0; i < jsonArr.length(); i++) {
            JSONObject jsonObj = jsonArr.getJSONObject(i);
            String invNum = jsonObj.getString("invoiceNumber");
        . . .                        
        // Prepare for writing to db
        DeliveryItem delItem = new DeliveryItem();
        delItem.set_invoiceNumber(invNum);
        . . .                        
        SQLiteHandlerDeliveryItem sqliteHandler = new  
            SQLiteHandlerDeliveryItem(SQLiteActivity.this, null);
        sqliteHandler.addDeliveryItem(delItem);
    }
}

...そして、そのクラスにはテーブルを作成するコードがあります:

public class SQLiteHandlerDeliveryItem extends SQLiteOpenHelper {
        . . .
public SQLiteHandlerDeliveryItem(Context context, SQLiteDatabase.CursorFactory factory)   
{
    super(context, DATABASE_NAME, factory, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
    String CREATE_DELIVERYITEMS_TABLE = "CREATE TABLE " +
            TABLE_DELIVERYITEMS + "("
            + COLUMN_ID + " INTEGER PRIMARY KEY," + COLUMN_INVOICENUM + " TEXT,"
            + COLUMN_UPCPLU + " TEXT," + COLUMN_VENDORITEMID + " TEXT,"
            + COLUMN_PACKSIZE + " INTEGER," + COLUMN_DESCRIPTION + " TEXT,"
            + COLUMN_COST + " INTEGER,"  + COLUMN_MARGIN + " INTEGER," + COLUMN_LISTPRICE + " INTEGER,"
            + COLUMN_DEPTNUM + " INTEGER," + COLUMN_SUBDEPT + " TEXT," + COLUMN_QTY + " TEXT"
            + ")";
    sqLiteDatabase.execSQL(CREATE_DELIVERYITEMS_TABLE);
}

それで...私は何を間違っているのですか、それとも正しいことをしていないのですか?

更新 3

テーブルが作成されていないのは事実です。LogCat の err メッセージは、その場合であることを示しています (「そのようなテーブルはありません: deliveryitems」です)。

私のコンストラクタは次のようになります。

@Override
public void onCreate(SQLiteDatabase db) {
    String CREATE_DELIVERYITEMS_TABLE = "CREATE TABLE " +
            TABLE_DELIVERYITEMS + "("
            + COLUMN_ID + " INTEGER PRIMARY KEY," + COLUMN_INVOICENUM + " TEXT,"
            + COLUMN_UPCPLU + " TEXT," + COLUMN_VENDORITEMID + " TEXT,"
            + COLUMN_PACKSIZE + " INTEGER," + COLUMN_DESCRIPTION + " TEXT,"
            + COLUMN_COST + " INTEGER,"  + COLUMN_MARGIN + " INTEGER," + COLUMN_LISTPRICE + " INTEGER,"
            + COLUMN_DEPTNUM + " INTEGER," + COLUMN_SUBDEPT + " TEXT," + COLUMN_QTY + " TEXT"
            + ")";
    db.execSQL(CREATE_DELIVERYITEMS_TABLE);
}

実際、このコードは入力されません。では、コンストラクターを呼び出すには、どのフープを通過する必要がありますか?

クラスをインスタンス化すると、次のようになると思います。

SQLiteHandlerDeliveryItem sqliteHandler = new 
    SQLiteHandlerDeliveryItem(SQLiteActivity.this, null);

呼び出された場合でも、コンストラクターは引数 (SQLiteDatabase db) が何であるかをどのように認識しますか? この値はどこから取得しますか?

私は1つのテーブルを持つデータベースを持っています。この 2 番目のテーブルの追加を拒否するだけです。

どこかで推奨されているように、データベースに追加するテーブルごとに SQLiteOpenHelper を拡張する別のクラスを追加しています。

その行に到達すると:

SQLiteHandlerDeliveryItem sqliteHandler = new 
    SQLiteHandlerDeliveryItem(SQLiteActivity.this, null);

...そして F7 を押してステップインすると、クラス コンストラクターに到達します。

public SQLiteHandlerDeliveryItem(Context context, SQLiteDatabase.CursorFactory factory)  
{
    super(context, DATABASE_NAME, factory, DATABASE_VERSION);
}

...しかし、onCreate イベントではありません。

したがって、deliveryitems テーブルを作成するコードに到達しないのは「当然」です。しかし、なぜ到達しないのですか - 到達させるにはどうすればよいですか?

4

3 に答える 3

1

まず、メソッドSQLiteOpenHelper.onCreate()はコンストラクターではありません。よくわかりませんが、質問で2つの概念を混同しているようです。


今、問題を解決しようとしています...

テーブルが作成されていないようです。のオンライン ヘルプからSQLiteOpenHelper.onCreate():

public abstract void onCreate (SQLiteDatabase db)

Called when the database is created for the first time. This is where the creation of tables and the initial population of the tables should happen.

したがって、このメソッドは、典型的なユース ケース (アプリが最初にインストールされたとき (最初にデータベースを使用したとき)) で 1 回だけ呼び出されます。その時点でonCreate()、実際のテーブルを作成する が呼び出されます。ただし、これはアプリを実行するたびに呼び出されるわけではありません。

これが問題かどうかを確認するための私のアドバイス -アプリをアンインストールして、もう一度やり直してください。このメソッドにブレークポイントを設定して、実際に実行されることを確認します。

アプリにデータベースがあり、更新してテーブルを追加し、アンインストールするのを忘れてしまうことがあります。別の正しい方法は、onUpgrade()メソッドを使用して新しいテーブルを追加することです。

これがどのように展開するか、または問題を誤解している場合はお知らせください。

于 2014-04-14T17:40:54.410 に答える