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() 方法中有一个断点,果然 - 它从未到达过。

为什么?以及如何强制调用构造函数,以便创建表?

奇怪的 [est] 事情是我还在另一个(工作)SQLiteOpenHelper 类中放置了一个断点,而且它没有达到......什么?!?它至少工作了一次,因为该表确实存在/是从该代码创建的。

所以很明显我的挥杆有一个洞;我有什么误解或做错了什么?

更新

我过早地将答案标记为答案。

至于:

“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)没有这样的表: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 msg 表明情况确实如此(它是“没有这样的表:delivertitems”)。

我的构造函数如下所示:

@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);

即使调用它,构造函数如何知道 arg (SQLiteDatabase db) 是什么——它从哪里得到这个值?

我确实有一个数据库,只有一张表。它只是拒绝添加第二个表。

正如有人推荐的那样,我正在添加一个单独的类,该类为我要添加到数据库的每个表扩展 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
  1. 你必须打电话getWritableDatabase()getReadableDatabase()在某个时候。

  2. 在您的构造函数中SQLiteHandlerDeliveryItem,您必须调用 super(...)。

于 2014-04-12T00:11:23.650 回答
1

首先,方法SQLiteOpenHelper.onCreate()不是构造函数。我不确定,但看起来你在问题中混合了这两个概念。


现在开始尝试解决问题...

似乎您的表没有被创建。从在线帮助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.

因此,对于一个典型的用例,这个方法只会被调用一次——当第一次安装应用程序时(第一次使用数据库)。在这一点上,onCreate()被称为创建实际表。但是每次运行应用程序时都不会调用它。

我的建议是检查这是否是问题 -卸载应用程序,然后重试。在此方法中放置一个断点以确保它确实可以运行。

有时会发生的情况是我们在应用程序上有一个数据库,然后更新东西以添加一个表,然后忘记卸载。另一种正确的方法是使用onUpgrade()添加新表的方法。

让我知道结果如何,或者我是否误解了这个问题。

于 2014-04-14T17:40:54.410 回答
0

正如我所希望的那样,它实际上是一个简单的解决方法:只需增加数据库版本的值。我在 p 上读到了这个。O'Reilly 的《Programming Android》中的 262 篇:

DATABASE_VERSION ...如果机器上的数据库版本低于DATABASE_VERSION,系统会运行你的onUpgrade方法将数据库升级到当前级别。

因此,您需要做的就是增加该数字:

    private static final int DATABASE_VERSION = 2; 
    // I changed it from "1" to "2", but you could change it to anything you want, I reckon (42, or 1776, or whatever).

增加版本值会导致 onUpgrade 运行,这会删除旧版本的数据库,然后调用 onCreate:

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

然后 onCreate() 事件就是这样做的——添加 DDL 来创建表。

这是在上下文中扩展 SQLiteOpenHelper 的类中的相关代码:

public class SQLiteHandlerDeliveryItem extends SQLiteOpenHelper {

private static final int DATABASE_VERSION = 2; 
private static final String DATABASE_NAME = "HHS.db";
private static final String TABLE_DELIVERYITEMS = "deliveryitems";

private static final String COLUMN_ID = "_id";
. . .
private static final String COLUMN_QTY = "quantity";

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

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

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

因此,在我看来,拥有多个扩展 SQLiteOpenHelper 的类是一件好事,因为您可以因此保持代码分离,而不是拥有一对巨大/巨大的 onUpgrade/onCreate 意大利面条。

于 2014-04-15T15:58:23.793 回答