1

I have some issue relating sqlitedatabase.i have create two thread.one is for webservice call and insert into database and second thread is for retrieving all database data.but i got some error:

 09-18 13:45:48.724: E/SQLiteDatabase(7189): android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5): , while compiling: PRAGMA journal_mode

my code is below:

Mainactivity.java

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        dbHelper = new DbHelper(this);

        setContentView(R.layout.activity_main);
        try {
            dbHelper.createDataBase();
        } catch (IOException e) {
            e.printStackTrace();
        }

        new Thread(new Runnable() {

            @Override
            public void run() {

                try {
                    Log.i("data", "webAllBrokers thread start");

                    GetAllBrokers(getApplicationContext());
                    // GetAllBrokers(getApplicationContext());
                    Log.i("data", "webAllBrokers thread complete");
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (XmlPullParserException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        }).start();
        new Thread(new Runnable() {

            @Override
            public void run() {
                Log.i("data", "SelectAllData thread start.");
                SelectAllData();
                Log.i("data", "SelectAllData thread complete");
            }

        }).start();

    }

    private void SelectAllData() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 100; i++) {
            TblBroker.SelectAll(dbHelper);
        }

    }

    public static void GetAllBrokers(Context context) throws IOException,
            XmlPullParserException, JSONException {
        // webservice call for retrieve data
        String result = GetAllBrokers(context, "Admin001");
        ArrayList<ModelBroker> lstBrokers = JsonParserGetAllBrokers
                .parserString(result);

        TblBroker.deleteAll(dbHelper);

        TblBroker.insert(dbHelper, lstBrokers);

    }

the other file is dbhelper file:

DbHelper.java

public class DbHelper extends SQLiteOpenHelper {


    // The Android's default system path of your application database.
    private static String PACKAGENAME = "com.example.webservicedemocallbackgroundwebservice";
    private static String DB_PATH = "/data/data/" + PACKAGENAME + "/databases/";
    private static String DB_NAME = "GRSL_Sales_DB.sqlite";
    public static int DELETED = 1;
    public static int UPDATED = 2;
    public static int NEW_RECORD = 3;
    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    private final Lock r = rwl.readLock();
    private final Lock w = rwl.writeLock();
    private SQLiteDatabase myDataBase;

    private final Context myContext;
    private String TAG = "DbHelper";

    /**
     * Constructor Takes and keeps a reference of the passed context in order to
     * access to the application assets and resources.
     * 
     * @param context
     */
    public DbHelper(final Context context) {
        super(context, DB_NAME, null, 1);
        this.myContext = context;

    }

    /**
     * Creates a empty database on the system and rewrites it with your own
     * database.
     * */
    public final void createDataBase() throws IOException {

        final boolean dbExist = checkDataBase();
        SQLiteDatabase db_Read = null;
        if (dbExist) {
            // do nothing - database already exist
        } else {
            // By calling this method and empty database will be created into
            // the default system path
            // of your application so we are gonna be able to overwrite that
            // database with our database.
            // By calling this method and empty database will be created into
            // the default system path
            // of your application so we are gonna be able to overwrite that
            // database with our database.
            // db_Read = this.getReadableDatabase(DB_Internal);
            db_Read = this.getReadableDatabase();
            db_Read.close();

            copyDataBase();

        }
    }

    /**
     * Restore whole database without any data
     * 
     * @throws IOException
     */
    public final void RestoreDatabase() throws IOException {
        SQLiteDatabase db_Read = this.getReadableDatabase();
        db_Read.close();

        copyDataBase();
        Log.i(TAG, "Database REstored");
    }

    /**
     * Check if the database already exist to avoid re-copying the file each
     * time you open the application.
     * 
     * @return true if it exists, false if it doesn't
     */
    private boolean checkDataBase() {
        final File dbFile = new File(DB_PATH + DB_NAME);
        return dbFile.exists();
    }

    /**
     * Copies your database from your local assets-folder to the just created
     * empty database in the system folder, from where it can be accessed and
     * handled. This is done by transfering bytestream.
     * 
     * @throws IOException
     * */
    private void copyDataBase() throws IOException {

        // Open your local db as the input stream
        final InputStream myInput = myContext.getAssets().open(DB_NAME);

        // Path to the just created empty db
        final String outFileName = DB_PATH + DB_NAME;

        // Open the empty db as the output stream
        final OutputStream myOutput = new FileOutputStream(outFileName);

        // transfer bytes from the inputfile to the outputfile
        final byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer)) > 0) {
            myOutput.write(buffer, 0, length);
        }

        // Close the streams
        myOutput.flush();
        myOutput.close();
        myInput.close();

    }

    public final synchronized SQLiteDatabase openDataBase() {
        // Log.i("data", "data openDataBase");
        // Open the database
        final String myPath = DB_PATH + DB_NAME;
        Log.i("database", "data openDataBase" + myDataBase);

        if (myDataBase == null) {
            Log.i("database", "data openDataBase");
            myDataBase = SQLiteDatabase.openDatabase(myPath, null,
                    SQLiteDatabase.OPEN_READWRITE);
            myDataBase.beginTransaction();
        } 
        return myDataBase;
    }

    @Override
    public final synchronized void close() {
        // Log.i("data", "data closeDataBase");

        if (myDataBase != null) {
            Log.i("database", "data closeDataBase");
            myDataBase.setTransactionSuccessful();
            myDataBase.endTransaction();
            myDataBase.close();
            myDataBase = null;
        }
        super.close();
    }

    @Override
    public void onCreate(final SQLiteDatabase arg0) {
    }

    @Override
    public void onUpgrade(final SQLiteDatabase arg0, final int arg1,
            final int arg2) {
    }
}

My table file is:

TblBroker.java

public class TblBroker {
    public static final String TABLENAME = "Broker";
    public static final String ID = "ID";
    public static final String SAPCODE = "SAPCode";
    public static final String DISCRIPTION = "Discription";
    public static final String ISACTIVE = "IsActive";
    public static final String ISDELETED = "IsDeleted";
    public static final String City = "City";

    /**
     * 
     * SelectAll
     * 
     * @param dbaConnection
     * @return ArrayList<ModelBroker>
     */
    public static ArrayList<ModelBroker> SelectAll(DbHelper dbaConnection) {
        Log.i("data", "SelectAll start");
        ArrayList<ModelBroker> broker_aList = new ArrayList<ModelBroker>();

        SQLiteDatabase sqldb = dbaConnection.openDataBase();
        Cursor cursor = sqldb.rawQuery("Select * From " + TblBroker.TABLENAME,
                null);
        if (cursor != null && !cursor.isClosed())// If CursorBroker is null then
                                                    // do
        // nothing
        {
            if (cursor.moveToFirst()) {
                do {
                    // Set broker information in model.
                    ModelBroker modelBroker = new ModelBroker();
                    modelBroker.setID(cursor.getInt(cursor
                            .getColumnIndex(TblBroker.ID)));
                    modelBroker.setSAPCode(cursor.getString(cursor
                            .getColumnIndex(TblBroker.SAPCODE)));
                    modelBroker.setDiscription(cursor.getString(cursor
                            .getColumnIndex(TblBroker.DISCRIPTION)));
                    modelBroker.setIsDeleted(cursor.getString(cursor
                            .getColumnIndex(TblBroker.ISDELETED)));
                    modelBroker.setIsActive(cursor.getString(cursor
                            .getColumnIndex(TblBroker.ISACTIVE)));
                    modelBroker.setCity(cursor.getString(cursor
                            .getColumnIndex(TblBroker.City)));
                    broker_aList.add(modelBroker);
                } while (cursor.moveToNext());
            }
            cursor.close();
        }
        Log.i("data", "SelectAll end");
        dbaConnection.close();
        return broker_aList;
    }

    public static long insert(DbHelper dbaConnection,
            ArrayList<ModelBroker> listbroker) {

        long id = 0;
        SQLiteDatabase sqldb = dbaConnection.openDataBase();

        for (int i = 0; i < listbroker.size(); i++) {

            ModelBroker broker = listbroker.get(i);
            ContentValues values = new ContentValues();
            values.put(TblBroker.SAPCODE, broker.getSAPCode());
            values.put(TblBroker.DISCRIPTION, broker.getDiscription());
            values.put(TblBroker.ISACTIVE, broker.getIsActive());
            values.put(TblBroker.ISDELETED, broker.getIsDeleted());
            values.put(TblBroker.City, broker.getCity());
            Log.i("data", "sqldb.isOpen()=" + sqldb.isOpen());
            id = sqldb.insert(TblBroker.TABLENAME, null, values);
        }

        Log.i("data", "1 st loop end");
        Log.i("data", "2nd  loop start");
        for (int i = 0; i < listbroker.size(); i++) {
            ModelBroker broker = listbroker.get(i);
            ContentValues values = new ContentValues();
            values.put(TblBroker.SAPCODE, broker.getSAPCode());
            values.put(TblBroker.DISCRIPTION, broker.getDiscription());
            values.put(TblBroker.ISACTIVE, broker.getIsActive());
            values.put(TblBroker.ISDELETED, broker.getIsDeleted());
            values.put(TblBroker.City, broker.getCity());
            id = sqldb.insert(TblBroker.TABLENAME, null, values);
        }

        Log.i("data", "2nd loop end");
        // Insert
        // query
        // of
        // SQLiteDatabase
        // class.
        dbaConnection.close();
        return id;

    }

    public static int deleteAll(DbHelper dbaConnection) {
        SQLiteDatabase sqldb = dbaConnection.openDataBase();
        int row = sqldb.delete(TABLENAME, null, null);// Delete

        sqldb.close();
        sqldb = null;
        return row;
    }

}

please give me some solution.when one thread is running and open db then at that time other thread is open db.so please find solution of concurrency problem.

4
  • Simplest way: do not use two threads for DB access ... but I guess it is not an option, really. Commented Sep 18, 2013 at 8:51
  • yes.but in my live app,two thread run simulteniously.so i have to create demo app and try to solve issue.but still issue remaining.please give me some other solution Commented Sep 18, 2013 at 8:53
  • try making your DB object volatile Commented Sep 18, 2013 at 9:04
  • Specifying a busy timeout whouldn't help? Commented Sep 18, 2013 at 10:26

2 Answers 2

7

Sqlite runs in Serialized mode on Android by default. This means that multiple threads can access the database simultaneously and thread-safety is maintained by using synchronized locks.

You can turn this off by using setLockingEnabled(boolean lockingEnabled). This will, however, make your db unsafe and you'll have to be careful and handle the synchronization yourself.

I would guess your problem lies in your architecture more than the threading. I suggest you re-think the architecture of your app so that you don't have to hack around with the thread-safety features of your db.

Sign up to request clarification or add additional context in comments.

2 Comments

setLockingEnabled(boolean lockingEnabled) was deprecated in API level 16
I am also facing similar issues. If Sqlite runs ins Serialized mode by default then how come this LockedException come because even if I am using multiple threads then Android itself will take care of all the operations? Also I am using singleton pattern for my helper class.
0

I had a similar problem problem inserting various row in different tables, try using this

   db.beginTransactionNonExclusive();
   try {
       //do some insertions or whatever you need
       db.setTransactionSuccessful();
   } finally {
       db.endTransaction();
   }

I tried with db.beginTransaction but it locked the bd

1 Comment

Could you elaborate on how this might solve the problem?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.