DatabaseLocked exception even after closing with db.close() and db.setTransactionSuccessful() - android

The application am working on will initially have one database with a table, say tbl_usr which will have only one record. Basically we are trying to keep one user per device. When the user logs in from the device with an auth code, his details will be fetched from server and stored in database. Next time if he tries to enter different auth code, which is valid but is not in table then he will not be allowed to proceed. Below is a common DBHelper class.
But whatever approach am trying, I am getting databaselocked exception, when tried for the 2nd time login. I've referred various links where in it was suggested to use different instance of database within method, but still it comes with error. Below is my Helper class
public class DBaseHelper extends SQLiteOpenHelper {
private static String CREATE_TABLE;
private static final String DATABASE_NAME="IPDB";
private static String UserMessage="";
private int tableType=0;
private ContentValues cValues;
private Cursor cursor;
public enum TableTypes{
Table1
};
public DBaseHelper(Context context){
super(context,context.getExternalFilesDir(null).getAbsolutePath()+"/"+DATABASE_NAME,null,1);
}
#Override
public void onCreate(SQLiteDatabase db){
TableTypes tableTypes=TableTypes.values()[tableType];
switch (tableTypes){
case Table1:
CREATE_TABLE="CREATE TABLE IF NOT EXISTS tbl_usr....";
break;
default:
break;
}
db.execSQL(CREATE_TABLE);
db.close();
System.out
.println("onCreate Method Done.");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
/*db.execSQL("DROP TABLE IF EXISTS "+LOGIN_TABLE);*/
onCreate(db);
}
/*this is the method which gets called from other class Like*/
/*helper.insertRecord(tableParams);*/
public HashMap<String,String> insertRecord(HashMap<String,String> dbaseParams){
HashMap<String,String> response=new HashMap<String,String>();
tableType=Integer.parseInt(dbaseParams.get("tableType"));
cValues = new ContentValues();
String TableName="";
TableTypes tableTypes=TableTypes.values()[tableType];
switch (tableTypes){
case Table1:
String AuthCode=dbParams.get("AuthCode");
/*if user exists then check if its the same user*/
if( CheckUserRecordExists(AuthCode) && empty(UserMessage) ){
response.put("isSuccess","true");
return response;
}
else {
if (!empty(UserMessage)) {
response.put("isSuccess", "false");
response.put("message",UserMessage);
return response;
}
/*add new user
Fill cValues declared above*/
TableName = "Table1";
}
break;
default:
break;
}
SQLiteDatabase dataBase = getWritableDatabase();
/*insert data into database*/
try {
dataBase.beginTransaction();
long rowID = dataBase.insertOrThrow(TableName, null, cValues);
dataBase.setTransactionSuccessful();
}
catch(Exception ex){
ex.printStackTrace();
}
finally {
dataBase.close();
}
response.put("isSuccess", "true");
return response;
}
private boolean CheckUserRecordExists(String authCode){
UserMessage="";
SQLiteDatabase dataBase=getReadableDatabase();
/*Exception here when comes for 2nd time after new installation*/
cursor = dataBase.query("Table1", new String[]{"COUNT(*)"}, null, null, null, null, null);
cursor.moveToFirst();
int iCount=cursor.getInt(0);
/*check if any record exist*/
if(iCount>0){
dataBase.close();
if(!cursor.isClosed()) cursor.close();
/*check if the code entered matches with the record existing*/
if(!CheckIsDataAlreadyInDBorNot("Table1","Auth_Code",authCode))
{
UserMessage="Invalid login!";
return false;
}
else return true;
}
else{
dataBase.close();
if(!cursor.isClosed()) cursor.close();
return false;
}
}
private boolean CheckIsDataAlreadyInDBorNot( String TableName,
String dbfield, String fieldValue) {
/*checking if user is same user*/
SQLiteDatabase dataBase=getReadableDatabase();
String[] columns = { dbfield };
String selection = dbfield + " =?";
String[] selectionArgs = { fieldValue };
String limit = "1";
Cursor cursor = dataBase.query(TableName, columns, selection, selectionArgs, null, null, null, limit);
boolean exists = (cursor.getCount() > 0);
cursor.close();
dataBase.close();
return exists;
}
public static boolean empty( final String s ) {
return s == null || s.trim().isEmpty();
}
}
I know its a huge code, but logic is simple. But the problem is database lock. Could someone let me know how I can make sure that database is always in valid state on each operation?

You have beginTransaction() but no matching calls to endTransaction(). An ongoing transaction keeps the database in a locked state and also keeps the internal reference count nonzero, so close() does not yet actually close the database.
The conventional pattern for transactional operations is
db.beginTransaction();
try {
// db operations that can throw
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
Also in your onCreate() you should not be closing the database since you don't own it.

Related

Suggestions to improve SQLite perfromance

I am saving data to an SQLite Database. It's taking a while for small amounts of data to be saved. I'm using: beginTransaction();
setTransactionSuccessful();, endTransaction(); etc but it doesn't improve performance. I'm considering switching to RealmDB if I can't improve this. Does anyone have any tips? Cheers
public enum DbSingleton {
INSTANCE;
private DatabaseHandler db;
public Context context;
private DatabaseHandler getDatabaseHandler(Context context) {
if (db != null) {
return db;
} else {
if (MainActivity.mainActivity == null) {
SQLiteDatabase.loadLibs(context);
return db = new DatabaseHandler(context); //make static context field in area this is used. e.g. main
} else {
return db = new DatabaseHandler(MainActivity.mainActivity);
}
}
}
//will provide one sample for reference now
public void insert(Context context, String table, ContentValues values) {
SQLiteDatabase.loadLibs(MainActivity.mainActivity);
//note this line
SQLiteDatabase sql = getDatabaseHandler(context).getWritableDatabase(DatabaseHandler.DB_PASSWD);
try {
sql.beginTransaction();
sql.insert(table, null, values);
// Log.i("Values being sent to db", values.toString());
sql.setTransactionSuccessful();
sql.endTransaction();
} catch (SQLiteException ex) {
Log.e("SQL EXCEPTION", ex.toString());
} finally {
sql.close();
}
}
public Cursor select(Context context, String statement, String[] selectArgs) {
SQLiteDatabase sql = getDatabaseHandler(context).getReadableDatabase(DatabaseHandler.DB_PASSWD);
if (selectArgs == null) {
return sql.rawQuery(statement, null);
} else {
return sql.rawQuery(statement, selectArgs);
}
}
public int Update(Context context, String table, ContentValues values, String where, String[] whereArgs) {
SQLiteDatabase sql = getDatabaseHandler(context).getWritableDatabase(DatabaseHandler.DB_PASSWD);
int count = -1;
try {
sql.beginTransaction();
count = sql.update(table, values, where, whereArgs);
sql.setTransactionSuccessful();
sql.endTransaction();
} catch (SQLiteException ex) {
Log.e("SQL EXCEPTION", ex.toString());
}
if (count == 0) count = -1;
return count;
}
public void Drop(Context context, String table) {
SQLiteDatabase sql = getDatabaseHandler(context).getWritableDatabase(DatabaseHandler.DB_PASSWD);
sql.execSQL("DROP TABLE IF EXISTS " + table);
}
public void Create(Context context, String table) {
SQLiteDatabase sql = getDatabaseHandler(context).getWritableDatabase(DatabaseHandler.DB_PASSWD);
sql.beginTransaction();
sql.execSQL(table);
sql.setTransactionSuccessful();
sql.endTransaction();
}
Wrapping your inserts in beginTransaction() and endTransaction() is only saving time when you do multiple inserts.
So always save your data to one table at once using the following format, this greatly improves performance:
ArrayList<String> itemsToInsert; //an array of strings you want to insert
db.beginTransaction();
ContentValues values = new ContentValues(1);
for (int i = 0; i < itemsToInsert.size(); i++) {
values.put('field', itemsToInsert.get(i));
db.insert(table, null, values);
}
db.setTransactionSuccessful();
db.endTransaction();
In addition, for selecting from a table, query() is performing slightly better than rawQuery(), but the difference is small.
Als check this article for more background information about SqlLite Performance:
sqlite-insertions
Android provides a new library as part of the architecture components called Room.
official doc says:
The Room persistence library provides an abstraction layer over SQLite
to allow for more robust database access while harnessing the full
power of SQLite.
Room Persistence Library
Save data in a local database using Room
More:
You can use the room with another awesome library (Paging Library) to handle paging and huge data sets
Paging library

Android-Not able to write to database

I am having issue with android app connectivity to SQLite database. I have an instance of SQLite database in Assets folder. 'Select' operation returns the data that is manually inserted into database.But, Write operations (Insert,Update,Delete) are failing. I was using 'this.getReadableDatabase()' and replaced with 'this.getWritableDatabase', Similarly,
SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY) was replaced with SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE), but still of no use. I am testing on Samsung Galaxy S i-90003 with 2.3.6 version. Some one please help me
db = this.getWritableDatabase();
ContentValues values = new ContentValues();
// values.put(KEY_ID,contact.getId());//Contact Id
values.put(KEY_NAME, contact.getName()); // Contact Name
values.put(KEY_IMAGE, contact.getImage()); // Contact Phone
// Inserting Row
try {
if(isTableExists(TABLE_IMAGES,true)) {
db.insert(TABLE_IMAGES, null, values);
}
}catch (Exception e) {
System.out.println("Error inserting:"+e.getMessage());
}
db.close(); // Closing database connection
public boolean isTableExists(String tableName, boolean openDb) {
if(openDb) {
if(db == null || !db.isOpen()) {
db = getWritableDatabase();
}
if(!db.isReadOnly()) {
db.close();
db = getWritableDatabase();
}
}
Cursor cursor = db.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '"+tableName+"'", null);
if(cursor!=null) {
if(cursor.getCount()>0) {
cursor.close();
return true;
}
cursor.close();
}
return false;
}
The problem seems about write permission on the database.
Android give you this 2 method to manage the creation and upgrade of a new database
public class MyDBHandler extends SQLiteOpenHelper {
#Override
public void onCreate(SQLiteDatabase arg0) {
//add here the sql code to create the database
}
#Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
// everytime you need to change the database place your sql code here
}
}
You should follow this tutorial to understand how to correct it
http://www.techotopia.com/index.php/An_Android_SQLite_Database_Tutorial

A strange behavior for regualr sqlite operation on android

I had a problem which I already solved but I still wants to know WHY
the solution solved it.
I wrote an android app that had a sqlite db after a couple of times I debugged it
The oncreate method in the db didnt got called (even though everything worked fine before)
After I changed the db version number from 1 to 2 everything worked fine again
Even though I uninstalled the app through the app manager and also removed the cache and
The local database information.
My question is as follows - does the local database data is saved somewhere else?
In case it doesn't - Why did it worked only after I upgraded the version number
not even when I erased all the app related data?
/**
* A class to handle sqlite reads/writes of user related data to be collected
*/
public class UserDataManager extends SQLiteOpenHelper {
// Class Variables
private final String TAG = UserDataManager.class.getSimpleName();
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
public static final String DATABASE_NAME = "tmc";
// Tables
private static final String TABLE_USER = "user";
// Tables and table columns names
private String CREATE_USER_TABLE;
private static final String COLUMN_USER_ID = "user_id";
private static final String COLUMN_USER_MAIL = "email";
private static final String COLUMN_USER_ACTIVE = "user_active";
private static final String COLUMN_USER_NAME = "name";
private static final String COLUMN_USER_PASSWORD = "password";
private static final String COLUMN_USER_PHONE_NUMBER = "phone_number";
/**
* Class constructor
*
* #param context
* The context to run in
*/
public UserDataManager(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Creating Tables
#Override
public void onCreate(SQLiteDatabase db) {
CREATE_USER_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_USER + " ("
+ COLUMN_USER_ID + " INTEGER PRIMARY KEY NOT NULL, "
+ COLUMN_USER_MAIL + " VARCHAR(64) NOT NULL, "
+ COLUMN_USER_NAME + " VARCHAR(64) NOT NULL, "
+ COLUMN_USER_PASSWORD + " VARCHAR(64) NOT NULL, "
+ COLUMN_USER_PHONE_NUMBER + " VARCHAR(64) NOT NULL, "
+ COLUMN_USER_ACTIVE + " INT NOT NULL);";
// create the tables
db.execSQL(CREATE_USER_TABLE);
}
// Upgrading database
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Drop older table if existed
db.execSQL("DROP TABLE IF EXISTS " + TABLE_USER);
// Create tables again
onCreate(db);
}
/**
* Adding a user to the database
*
* #param userId
* The created user id
* #param userName
* The user name
* #param userEmail
* The user email
* #param userPassword
* The user password
* #param userPhoneNumber
* The user phone number
* #param isActive
* Set to 1 if the user is active 0 otherwise
* #return True if the user added successfully false otherwise
*/
public boolean AddUser(int userId, String userName, String userEmail,
String userPassword, String userPhoneNumber, boolean isActive) {
// method variables
long rowId;
boolean pass = false;
int active = isActive ? 1 : 0;
SQLiteDatabase db = null;
ContentValues row = null;
// try to add the user to the db
try {
row = new ContentValues();
db = this.getWritableDatabase();
db.delete(TABLE_USER, null, null);
row.put(COLUMN_USER_ID, userId);
row.put(COLUMN_USER_NAME, userName);
row.put(COLUMN_USER_MAIL, userEmail);
row.put(COLUMN_USER_PASSWORD, userPassword);
row.put(COLUMN_USER_CAR_NUMBER, userPhoneNumber);
row.put(COLUMN_USER_ACTIVE, active);
rowId = db.insert(TABLE_USER, null, row);
if (rowId > -1) {
pass = true;
}
} catch (SQLException exception) {
Log.e(TAG, exception.getMessage());
} finally {
if (db != null) {
// close database connection
db.close();
}
}
return pass;
}
/**
* Get the current registered user
*
* #return The id of the column of the registered user
*/
public int GetRegisteredUserId() {
// method variables
int columnIndex = -1;
int userId = -1;
SQLiteDatabase db = null;
Cursor cursor = null;
// try to get the user from the database
try {
db = this.getReadableDatabase();
cursor = db.query(TABLE_USER, new String[] { COLUMN_USER_ID },
null, null, null, null, null);
if (cursor != null) {
boolean moved = cursor.moveToFirst();
if (moved) {
columnIndex = cursor.getColumnIndex(COLUMN_USER_ID);
if (columnIndex > -1) {
userId = cursor.getInt(columnIndex);
}
}
}
} catch (SQLException exception) {
Log.e(TAG, exception.getMessage());
} finally {
if (cursor != null)
// release cursor
cursor.close();
if (db != null)
// close database connection
db.close();
}
return userId;
}
/**
* Get the current user email
*
* #return The id of the column of the registered user
*/
public String GetRegisteredUserEmail() {
// method variables
int columnIndex = -1;
String userEmail = null;
SQLiteDatabase db = null;
Cursor cursor = null;
// try to get the user from the database
try {
db = this.getReadableDatabase();
cursor = db.query(TABLE_USER, new String[] { COLUMN_USER_MAIL },
null, null, null, null, null);
if (cursor != null) {
boolean moved = cursor.moveToFirst();
if (moved) {
columnIndex = cursor.getColumnIndex(COLUMN_USER_MAIL);
if (columnIndex > -1) {
userEmail = cursor.getString(columnIndex);
}
}
}
} catch (SQLException exception) {
Log.e(TAG, exception.getMessage());
} finally {
if (cursor != null)
// release cursor
cursor.close();
if (db != null)
// close database connection
db.close();
}
return userEmail;
}
/**
* Get the current user password
*
* #return The password of the current logged user
*/
public String GetRegisteredUserPassword() {
// method variables
int columnIndex = -1;
String userPassword = null;
SQLiteDatabase db = null;
Cursor cursor = null;
// try to get the user from the database
try {
db = this.getReadableDatabase();
cursor = db.query(TABLE_USER,
new String[] { COLUMN_USER_PASSWORD }, null, null, null,
null, null);
if (cursor != null) {
boolean moved = cursor.moveToFirst();
if (moved) {
columnIndex = cursor.getColumnIndex(COLUMN_USER_PASSWORD);
if (columnIndex > -1) {
userPassword = cursor.getString(columnIndex);
}
}
}
} catch (SQLException exception) {
Log.e(TAG, exception.getMessage());
} finally {
if (cursor != null)
// release cursor
cursor.close();
if (db != null)
// close database connection
db.close();
}
return userPassword;
}
/**
* Get number of rows in the user table
*
* #return the number of the rows in the user table (How many users are
* saved in the DB)
*/
public int GetRowCount() {
// method variables
int rowsCount = 0;
SQLiteDatabase db = null;
Cursor cursor = null;
// try to get the user from the database
try {
db = this.getReadableDatabase();
cursor = db.query(TABLE_USER, null, null, null, null, null, null);
if (cursor != null) {
boolean moved = cursor.moveToFirst();
if (moved) {
do {
rowsCount++;
} while (cursor.moveToNext());
}
}
} catch (SQLException exception) {
Log.e(TAG, exception.getMessage());
} finally {
if (cursor != null)
// release cursor
cursor.close();
if (db != null)
// close database connection
db.close();
}
return rowsCount;
}
/**
* Remove a user from the database
*
* #param userId
* The user id
*/
public void LogoutUser() {
// method variables
SQLiteDatabase db = null;
// try to remove a user from the database
try {
db = this.getWritableDatabase();
onUpgrade(db, DATABASE_VERSION, DATABASE_VERSION);
} catch (SQLException exception) {
Log.e(TAG, exception.getMessage());
} finally {
if (db != null) {
// close database connection
db.close();
}
}
}
/**
* Set a user to be active or not
*
* #param isActive
* 1 if the cigarette is active 0 otherwise
* #return True if the cigarette active field has changed false otherwise
*/
public boolean SetUserActive(boolean isActive) {
// method variables
int rowsAffected;
int active = isActive ? 1 : 0;
long userId;
String userIdString;
boolean pass = true;
SQLiteDatabase db = null;
ContentValues values = null;
// try to remove a device from the database
try {
userId = GetRegisteredUserId();
if (userId > -1) {
userIdString = String.valueOf(userId);
db = this.getWritableDatabase();
values = new ContentValues();
values.put(COLUMN_USER_ACTIVE, active);
rowsAffected = db.update(TABLE_USER, values, COLUMN_USER_ID
+ " = ?", new String[] { userIdString });
if (rowsAffected != 1) {
pass = false;
}
}
} catch (SQLException exception) {
Log.e(TAG, exception.getMessage());
} finally {
if (db != null) {
// close database connection
db.close();
}
}
return pass;
}
}
Notes -
1. Please note that my device is rooted and so after inserting the data to the db im changing the permissions on the db file for 777 so I can pull it from the phone to see whats in it (i.e. did the query pass or not)
2. The error that is being thrown is "android.database.sqlite.SQLiteException: no such table: user "
Chocolate chips cookies will be granted for any answer... =)
Why did it worked only after I upgraded the version number not even when I erased all the app related data?
As soon as you start working with either of getReadableDatabase() ,getWriteableDatabase() or any other SQLiteHelper class code. The first method calls is onCreate(SQLiteDatabase db) which creates Database under your application database path
/data/data/PACKAGE_NAME/databases/tmc (in your case).
If you modify your Database structure in SQliteHelper the first method get called is onUpgrage() which checks whether Database_Version get modified or not. If it's then it execute onUpgrade() with series of DROP TABLE IF EXIST followed by onCreate() which again create your database with new structure under your application path by replacing your previous database file.
Clearing Cached data using Application Manager indeed clear database and cached data of that application. But SQLiteHelper did check for Database_Version with old and new one. If new one is greater than old one. It does call onUpgrage() followed by onCreate().
When you intent to use Database with Android Application it get store under /data/data/PACKAGE_NAME/databases/tmc with application process security. Unable to access database file unless you have rooted Android device in which you already have.
One can create Developer Options or anything you like just to pull database from your application process to SD Card for unrooted devices.
Copy database file from application process path to SD Card for unrooted devices.
try {
File sd = Environment.getExternalStorageDirectory();
File data = Environment.getDataDirectory();
if (sd.canWrite()) {
String currentDBPath = "/data/data/" + getPackageName() + "/databases/ZnameDB"; //Your DATABASE_NAME
String backupDBPath = "ZnameDB_Dev.db"; //DATABASE_COPY_NAME UNDER SDCARD
File currentDB = new File(currentDBPath);
File backupDB = new File(sd, backupDBPath);
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
Toast.makeText(SettingsActivity.this, "Database Transfered!", Toast.LENGTH_SHORT).show();
}
}
} catch (Exception e) {
Log.e(TAG, e.toString());
}
Answering your first question, all data is stored under YOUR_PACKAGE/databases/DATABASE.db only.
If you erase app through app manager all data is removed, just package remains. If you uninstall your app everything is cleared including package folder. Even if you set for your app install location to external SD card, database is stored internally anyway.
From documentation:
The .apk file is saved on the external storage, but all private user
data, databases, optimized .dex files, and extracted native code are
saved on the internal device memory.
SQLiteOpenHelper logic is simple:
checks if DB exists, if not new DB is created
retrieve DB version, initial value is 0, that's why in your app minimum value for DB version is 1 to call onCreate() method at least once
if version is equal to 0, onCreate() is called, or
if version is different than the one provided by your code onUpgrade() or onDowngrade() is called
So, whenever you upgrade your scheme, version number MUST be increased, there is no argue about that, in order to allow your app work properly.
Now, in your specific case I can only guess. I would say that erasing your package was not entirely successful and bits of data was left, especially if you mentioned that you did some manual modification on DB file. Maybe it has something to do with Android version running on your device but you didn't mentioned which one is it.
That's all. I hope my answer is satisfying.
Can you exec PRAGMA user_version; in your adb to get the db version? According to the source code of SQLiteOpenHelper, SQLite.getVersion() equals to SQLiteOpenHelper.mNewVersion, so onCreate() method won't be invoked. When you chmod 777 on db file, the user_version will be modified too.
Assuming the databases are not deleted while uninstalling app, this seems plausible. The databases are stored here DDMS/data/data/PACKAGE_NAME/databases/YOUR_DB_FILE. You can only see this if your phone is rooted.
Please check whether this assumption is true and correct me if I am wrong.
Thanks

Sqlite Check if Table is Empty [duplicate]

This question already has answers here:
How can i check to see if my sqlite table has data in it?
(13 answers)
Closed 4 years ago.
Well, I have a databse and it has lots of table. but generally tables are empty.
I want check if a database table is empty.
IF table is empty, program will fill it.
public static long queryNumEntries (SQLiteDatabase db, String table)
I will use it but it requre API 11.
you can execute select count(*) from table and check if count> 0 then leave else populate it.
like
SQLiteDatabase db = table.getWritableDatabase();
String count = "SELECT count(*) FROM table";
Cursor mcursor = db.rawQuery(count, null);
mcursor.moveToFirst();
int icount = mcursor.getInt(0);
if(icount>0)
//leave
else
//populate table
Do a SELECT COUNT:
boolean empty = true
Cursor cur = db.rawQuery("SELECT COUNT(*) FROM YOURTABLE", null);
if (cur != null && cur.moveToFirst()) {
empty = (cur.getInt (0) == 0);
}
cur.close();
return empty;
public boolean isEmpty(String TableName){
SQLiteDatabase database = this.getReadableDatabase();
long NoOfRows = DatabaseUtils.queryNumEntries(database,TableName);
if (NoOfRows == 0){
return true;
} else {
return false;
}
}
Optimal Solutions
public boolean isMasterEmpty() {
boolean flag;
String quString = "select exists(select 1 from " + TABLE_MASTERS + ");";
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.rawQuery(quString, null);
cursor.moveToFirst();
int count= cursor.getInt(0);
if (count ==1) {
flag = false;
} else {
flag = true;
}
cursor.close();
db.close();
return flag;
}
Here is a better option:
public boolean validateIfTableHasData(SQLiteDatabase myDatabase,String tableName){
Cursor c = myDatabase.rawQuery("SELECT * FROM " + tableName,null);
return c.moveToFirst();
}
This is how you can do it -
if(checkTable("TABLE"))
{
//table exists fill data.
}
Method to check table -
public static boolean checkTable(String table) {
Cursor cur2 = dbAdapter.rawQuery("select name from sqlite_master where name='"
+ table + "'", null);
if (cur2.getCount() != 0) {
if (!cur2.isClosed())
cur2.close();
return true;
} else {
if (!cur2.isClosed())
cur2.close();
return false;
}
}
I think, this solution is better:
boolean flag;
DatabaseHelper databaseHelper = new DatabaseHelper(getApplicationContext(), DatabaseHelper.DATABASE_NAME, null, DatabaseHelper.DATABASE_VERSION);
try {
sqLiteDatabase = databaseHelper.getWritableDatabase();
} catch (SQLException ex) {
sqLiteDatabase = databaseHelper.getReadableDatabase();
}
String count = "SELECT * FROM table";
Cursor cursor = sqLiteDatabase.rawQuery(count, null);
if (cursor.moveToFirst()){
flag = false;
} else {
flag = true;
}
cursor.close();
sqLiteDatabase.close();
return flag;
moveToFirst() check table and return true, if table is empty. Answer that is marked correct - uses extra check.

SQLite queries to create a defined Java Object

I have a SQLite table of this tipe
Table Vehicles:
CATEGORY COUNTRY ID NAME EMAIL
A GE 1 BMW sample1#salple.it
A GE 2 Lamborghini sample2#salple.it
B GE 3 BMW sample3#salple.it
I want to select all the entries that have a specified name or a specified category and pass all the parameters how each row in a constructor
Vehicle(String category, String country, int id, String name, String email)
I have implemented this adapter using some tutorials:
public class TestAdapter
{
protected static final String TAG = "DataAdapter";
private final Context mContext;
private SQLiteDatabase mDb;
private DataBaseHelper mDbHelper;
public TestAdapter(Context context)
{
this.mContext = context;
mDbHelper = new DataBaseHelper(mContext);
}
public TestAdapter createDatabase() throws SQLException
{
try
{
mDbHelper.createDataBase();
}
catch (IOException mIOException)
{
Log.e(TAG, mIOException.toString() + " UnableToCreateDatabase");
throw new Error("UnableToCreateDatabase");
}
return this;
}
public TestAdapter open() throws SQLException
{
try
{
mDbHelper.openDataBase();
mDbHelper.close();
mDb = mDbHelper.getReadableDatabase();
}
catch (SQLException mSQLException)
{
Log.e(TAG, "open >>"+ mSQLException.toString());
throw mSQLException;
}
return this;
}
public void close()
{
mDbHelper.close();
}
public boolean SaveVehicles(String category , String country, String id, String name, String email)
{
try
{
ContentValues cv = new ContentValues();
cv.put("Category", category);
cv.put("Country", country);
cv.put("id", id);
cv.put("Name", name);
cv.put("Email", email);
mDb.insert("Vehicles", null, cv);
Log.d("SaveVehicles", "informationsaved");
return true;
}
catch(Exception ex)
{
Log.d("SaveVehicles", ex.toString());
return false;
}
}
}
But I don't know how I could implement the various get methods that I need, to meet a solution to my problem.
Creating an object from a SQL query would look something like this
/**
* #return Returns a list of all objects.
*/
public ArrayList<Object> getAllObjects()
{
// Select All Query
String selectQuery = "SELECT * FROM SOME_TABLE";
// Get the isntance of the database
SQLiteDatabase db = this.getWritableDatabase();
//get the cursor you're going to use
Cursor cursor = db.rawQuery(selectQuery, null);
//this is optional - if you want to return one object
//you don't need a list
ArrayList<Object> objectList = new ArrayList<Object>();
//you should always use the try catch statement incase
//something goes wrong when trying to read the data
try
{
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
//the .getString(int x) method of the cursor returns the column
//of the table your query returned
Object object= new Object(Integer.parseInt(cursor.getString(0)),
Integer.parseInt(cursor.getString(1)),
Integer.parseInt(cursor.getString(2)),
cursor.getString(3),
cursor.getString(4),
cursor.getString(5),
Boolean.parseBoolean(cursor.getString(6))
);
// Adding contact to list
objectList.add(object);
} while (cursor.moveToNext());
}
}
catch (SQLiteException e)
{
Log.d("SQL Error", e.getMessage());
return null;
}
finally
{
//release all your resources
cursor.close();
db.close();
}
return objectList;
}
The code above assumes you have some table in your database named "SOME_TABLE" and that you have an object that takes 7 parameters but you should be able to alter the snippet to make it work for you.
You need to query your database for the data, and then iterate through the returned cursor to pull out the data you need and put it into strings to feed into your constructor.
The query would look something like this (using the info you provided and the query method):
public Cursor fetchList(String category) {
return mDb.query("Vehicles", new String[] { "CATEGORY", "COUNTRY", "ID", "NAME", "EMAIL" }, "Category =" + category,
null, null, null, null);
}
Note that this is a basic query and subject to SQL injection attacks, It should be parameterized to make it less vulnerable, unless you are not going to allow the user to type in the category and rather have them pick from a list you provide.
Anyway, that would return your data in a cursor, with one row for each record that matched the search parameters. From there, you would need to iterate through the returned cursor and pull the data out of it and into strings you can use.

Categories

Resources