Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using SQLite Readable and Writable Database Together

I am writing a code for Android which will require both Readable and Writable Database at the same time. And I am getting following error:

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)

The piece of code making error, as per what I am guessing is here:

    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
        {

Error in this line Line No. 215

            SQLiteDatabase dbWrite = this.getWritableDatabase();

Error in this line Line No. 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");
}
like image 547
Sharda Singh Avatar asked May 21 '13 08:05

Sharda Singh


People also ask

Can you read and write SQLite at the same time?

First, by default, multiple processes can have the same SQLite database open at the same time, and several read accesses can be satisfied in parallel. In case of writing, a single write to the database locks the database for a short time, nothing, even reading, can access the database file at all.

Does SQLite support multiple connections?

SQLite does support multiple concurrent connections, and therefore it can be used with a multi-threaded or multi-process application. The catch is that when SQLite opens a write transaction, it will lock all the tables.

When should you not use SQLite?

A good rule of thumb is to avoid using SQLite in situations where the same database will be accessed directly (without an intervening application server) and simultaneously from many computers over a network. SQLite will normally work fine as the database backend to a website.

Does SQLite support concurrency?

Concurrency in SQLiteSQLite (and RSQLite) supports concurrent access to the same database, through multiple database connections, possibly from multiple processes.


1 Answers

If you need to read and write the same database, I suggest you open the database once in writable mode. Writable database can also be read, therefore you should have no problem doing everything you need. According to the getWritableDatabase documentation, this method is used to

Create and/or open a database that will be used for reading and writing.

Hence there's no need to open it twice in two separate modes. Open it once as writable, do everything you need to do, then close it.

like image 59
Aleks G Avatar answered Nov 10 '22 04:11

Aleks G