【问题标题】:Using SQLite Readable and Writable Database Together结合使用 SQLite 可读可写数据库
【发布时间】:2013-05-21 08:02:35
【问题描述】:

我正在为Android 编写代码,这将同时需要ReadableWritable Database。我收到以下错误:

05-21 13:27:47.079: E/SQLiteDatabase(8326): close() was never explicitly called on database '/data/data/com.example.devicecontrolpanel/databases/AlarmSystem' 
05-21 13:27:47.079: E/SQLiteDatabase(8326): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
05-21 13:27:47.079: E/SQLiteDatabase(8326):     at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:2052)
05-21 13:27:47.079: E/SQLiteDatabase(8326):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1087)
05-21 13:27:47.079: E/SQLiteDatabase(8326):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1050)
05-21 13:27:47.079: E/SQLiteDatabase(8326):     at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1136)
05-21 13:27:47.079: E/SQLiteDatabase(8326):     at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:1041)
05-21 13:27:47.079: E/SQLiteDatabase(8326):     at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
05-21 13:27:47.079: E/SQLiteDatabase(8326):     at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:165)
05-21 13:27:47.079: E/SQLiteDatabase(8326):     at com.example.devicecontrolpanel.DataBaseAdapter.addDeviceOnSearch(DataBaseAdapter.java:215)
05-21 13:27:47.079: E/SQLiteDatabase(8326):     at com.connection.DeviceInformation.<init>(DeviceInformation.java:39)
05-21 13:27:47.079: E/SQLiteDatabase(8326):     at com.example.devicecontrolpanel.TestActivity$DeviceSearcher$3.run(TestActivity.java:251)

根据我的猜测,代码生成错误在这里:

    public int addDeviceOnSearch(DeviceInformation device) //Final and done
    {
        SQLiteDatabase dbRead = this.getReadableDatabase();

        String[] columDevice = {DEVICE_ID, DEVICE_NAME, DEVICE_IP, DEVICE_TYPE};
        String[] columPin = {PIN_ID, PIN_NO, PIN_NAME, PIN_CURRENT_STATUS};

        Cursor cursorDevice = dbRead.query(DEVICE_TABLE, columDevice, DEVICE_MAC+"=?", new String[] {device.getMAC()}, null, null, null);
        dbRead.close();
        if(cursorDevice==null)
        {
            SQLiteDatabase dbWrite = this.getWritableDatabase();
            ContentValues values = new ContentValues();
            //New Device
            values.put(DEVICE_IP, device.getIP());
            values.put(DEVICE_MAC, device.getMAC());
            values.put(DEVICE_NAME, device.getDeviceName());
            values.put(DEVICE_TYPE, device.getType());
            long devId = dbWrite.insert(DEVICE_TABLE, null, values);
            device.setId((int) devId);
            dbWrite.close();
        }
        else
        {

此行第 215 行错误

            SQLiteDatabase dbWrite = this.getWritableDatabase();

此行第 215 行错误

            ContentValues values = new ContentValues();
            //Already Exist
            device.setId(Integer.parseInt(cursorDevice.getString(0)));
            device.setDeviceName(cursorDevice.getString(1));

            values.put(DEVICE_IP, device.getIP());
            values.put(DEVICE_TYPE, device.getType());
            dbWrite.update(DEVICE_TABLE,values, DEVICE_ID+ " = ?",new String[] {String.valueOf(device.getId())});
            values  = new ContentValues();
            dbWrite.close();
            dbRead = this.getReadableDatabase();
            Cursor cursorPin = dbRead.query(PIN_TABLE, columPin, PIN_DEVICE_ID+"=?", new String[] {String.valueOf(device.getId())}, null, null, null);
            if(cursorPin==null)
            {
                device.setDevicePin(null);
            }
            else
            {
                cursorPin.moveToFirst();
                List<DevicePinDetail> devicePins = new ArrayList<DevicePinDetail>();
                do
                {
                    int pinId=Integer.parseInt(cursorPin.getString(0));
                    int pin_no=Integer.parseInt(cursorPin.getString(1));
                    String PinName =cursorPin.getString(2);
                    int pinStatus=Integer.parseInt(cursorPin.getString(3));
                    int PinDeviceId=device.getId();
                    devicePins.add(new DevicePinDetail(pinId, pin_no, PinName, PinDeviceId, pinStatus));
                }while(cursorPin.moveToNext());
                device.setDevicePin(devicePins);
            }   
        }
        dbRead.close();
        return device.getId();
    }

onCreate()

@Override
public void onCreate(SQLiteDatabase db)
{
    String CREATE_ALARM_TABLE = "Create Table "+TABLE_NAME+"("
            +KEY_ALARM_ID+" integer primary key AUTOINCREMENT, "+KEY_DESC+" TEXT, "+KEY_REPEAT_DAY+ " TEXT,"
            +KEY_REPEAT_TYPE+" integer, "+KEY_CALENDAR+" TEXT, "+KEY_DEVICE_MAC+" TEXT,"+KEY_DEVICE_IP+" TEXT,"
            +KEY_DEVICE_TYPE+" integer, "+KEY_JSON+" TEXT,"+KEY_ACTIVE+" integer, "+KEY_DEVICE_NAME+" text);";

    String CREATE_DEVICE_TABLE = "Create Table "+ DEVICE_TABLE+"("
            +DEVICE_ID+" integer primary key AUTOINCREMENT, "+DEVICE_MAC+" TEXT, "+DEVICE_NAME+" text, "+DEVICE_IP+" TEXT,"+DEVICE_TYPE+" integer);";

    String CREATE_PIN_TABLE = "Create Table "+ PIN_TABLE + "("
            +PIN_ID+" integer primary key AUTOINCREMENT, "+PIN_NO+" integer, "+PIN_NAME+" text, "+PIN_CURRENT_STATUS+" integer, "
            +PIN_DEVICE_ID+" integer);";

    String CREATE_SETTING_TABLE = "Create Table "+SETTINGS_TABLE+" ("
            +SETTINGS_ID+" integer primary key AUTOINCREMENT, "
            +SETTINGS_COMPUTER+" integer, "+SETTINGS_RASPBERRY+ " integer, "+SETTINGS_FLYPORT+ " integer,"
            +COMPUTER_IP + " text,"+COMPUTER_PORT_SEND+" integer, "+RASPBERRY_IP+" text,"+RASPBERRY_PORT_SEND+" integer,"
            + " text,"+COMPUTER_PORT_RECV+" integer,"+RASPBERRY_PORT_RECV+" integer);";

    db.execSQL(CREATE_PIN_TABLE);
    db.execSQL(CREATE_ALARM_TABLE);
    db.execSQL(CREATE_DEVICE_TABLE);
    db.execSQL(CREATE_SETTING_TABLE);

    ContentValues values = new ContentValues();
    values.put(SETTINGS_COMPUTER, 1);
    values.put(SETTINGS_RASPBERRY, 1);
    values.put(SETTINGS_FLYPORT, 1);
    values.put(COMPUTER_IP, "225.4.5.6");
    values.put(RASPBERRY_IP, "225.4.5.6");
    values.put(COMPUTER_PORT_SEND, 5000);
    values.put(COMPUTER_PORT_RECV, 5003);
    values.put(RASPBERRY_PORT_SEND, 6000);
    values.put(RASPBERRY_PORT_RECV, 6003);
    db.insert(SETTINGS_TABLE, null, values);

    System.out.println("Values added");
}

【问题讨论】:

  • 显示你的 onCreate 方法。
  • 你在同时阅读和写作。我想那是他的问题。我不确定
  • 你...!!我什至认为……那应该是什么解决方案。?

标签: java android sql sqlite


【解决方案1】:

如果你需要读写同一个数据库,我建议你以可写模式打开一次数据库。也可以读取可写数据库,因此您可以轻松完成所需的一切。根据getWritableDatabase documentation,此方法用于

创建和/或打开一个用于读写的数据库。

因此无需在两种不同的模式下打开两次。以可写形式打开一次,做所有你需要做的,然后关闭它。

【讨论】:

  • getReadableDatabase有什么用呢?
  • @ShardaSingh getReadableDatabase 如果更快的话。如果你不需要写任何东西,那么应该使用可读数据库。但是,在可写模式下打开一次比可读然后可写要快得多。查看文档SQLiteOpenHelper 文档,那里有一些信息。
  • 他们本可以更好地命名该方法。
  • 更快我不认为如果你打开 SQLlite 类你会看到 getReadable 和 getWritable 都返回相同的实例,所以没有区别读取本身更快,你可以说
【解决方案2】:

看看你是否想避免这个问题,这里有几件事 一 由于您的数据库有多个连接,它们没有被序列化或锁定是错误的,所以如果您从多个线程和不同的连接访问您的数据库,那么如果一个线程正在写入它会锁定 db 文件和任何将失败的操作发布 所以要让它工作使用

  1. SQLLite 中的 WAL 模式,您可以根据线程进行一次写入操作和并发读取
  2. 保留一个单例或单个 DB 实例,以便对跨多个线程共享的一个连接上的所有操作进行序列化

【讨论】:

    猜你喜欢
    • 2011-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-22
    • 1970-01-01
    相关资源
    最近更新 更多