Refactoring table insertion methods in a subclass of SQLiteOpenHelper - android

I hope I'm not asking something that has a direct answer in embedded database programming. If I am, please direct me to the answer and I will close this question.
My question is the following: suppose I have a subclass of SQLiteOpenHelper in my android application. This subclass overrides the appropriate methods, and also creates a database (say database.db) and I want it to have some functionality for inserting things into the database (i.e to each table). How can I write these methods so that there is little code duplication? The reason I ask this is because each insertion method does exactly the same thing in general: get the database for writing, create the ContentValues object, fill it with the right data, and use the insert method in SQLiteOpenHelper.
The other option, if I don't want to have an insert method per table, is to just run raw queries from a reference I have to this subclass of SQLiteOpenHelper. To be honest, neither seem to be good solutions to the problem of having an easy to use API to insert/delete/query a database via this class. I would love some help, thanks!

I hope I understood you correctly. You need to move your SQLiteOpenHelper class in another class file and reuse code of it every time you need to open your db, get query or insert values?
If yes - I can provide links for you to read abroad SO, also some snippets for you.
Lets suggest you have subclass
class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {...}
public void onCreate(SQLiteDatabase db) {...}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {...}
}
Create new java class in your package named DBHelper and move whole code of DBHelper inside of it. Than, when you need reference of db in your code, use this:
public class MainActivity extends AppCompatActivity{
DBHelper dbHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new DBHelper(this);
SQLiteDatabase db = dbHelper.getWritableDatabase();
//rest of your code goes here
}
If you want to get data from db without typing code for cursor and query each time, you can go and read answer, provided by OschtärEi (link)

Related

Can a SQLite database be Open, but not Readable?

I am working on Android application and want to ask if it might be possible for a SQLiteDatabase object, which is the object used to interact with the underlying SQLite db, to be Open (as in returns TRUE on db.isOpen()), but still not be readable?
What scenarios are possible? Locking?
Example:
SQLiteAppHelper sqliteHelper = SQLiteAppHelper.getInstance(context);
SQLiteDatabase appDB = sqliteHelper.getReadableDatabase();
Note: The code above is using a class that extends SQLiteOpenHelper.

SQLiteDatabase and Cursor leaks and close() calls

I need some help on database and cursor managing. I noticed that, when entering /leaving certain fragments, I get:
W/SQLiteConnectionPool﹕ A SQLiteConnection object for database '+data+data+database' was leaked! Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.
That made me go back from scratch and check what I'm doing and when. I have:
a DatabaseHelper class extending SQLiteOpenHelper, with just some methods for creating and updating the db;
a DatabaseManager class, extending nothing. I use this, among other things, to keep a single reference to a DatabaseHelper object:
public class DatabaseManager {
private DatabaseHelper h; //class extending SQLiteOpenHelper
public DatabaseManager(Context c) {
if (h==null) {
h = new DatabaseHelper(c.getApplicationContext()); }
public Cursor query(...) {
SQLiteDatabase db = h.getReadableDatabase();
return db.rawQuery(...)
}
public void closeConnection() {
SQLiteDatabase db = h.getWritableDatabase();
db.close();
h.close();
}
}
in this class, some methods querying the database and returning a Cursor object;
in this class, a closeConnection() method, which I'm not really sure of.
I use this class from fragments, calling each time new DatabaseManager(getActivity()). This should not create a new helper reference. Right now I am:
calling Cursor.close() as soon as I got the information I wanted from the query;
never calling open() on my helper neither on my SQLiteDatabase, although I read somewhere that should be done. When exactly? Why it all works even without calling it?
calling manager.closeConnection() in the onStop() method of fragments that make use of my database. As you can see, that calls close on h (a reference to the helper class) and on a readable SQLiteDatabase object. However, I'm not really sure about that, because it closes the helper reference h without making it null, so maybe there are some problems with future calls to new DatabaseManager() ? Maybe dealing with database with a singleton pattern does not require you to call h.close()?
Apart from that, needless to say (that's why I'm asking), when switching through fragments I get the above mentioned warning. What's wrong? What should I do? What does end transactions in progress mean? Should I modify my closeConnection() method, call it in different lifecycle times, or don't call it at all?
After embarrassing issue pointed out by #Selvin, I made h static. Now if I remove any call to closeConnection(), it all works well and I don't get any warnings. That means I'm never calling neither h.close() or db.close(). Is that ok? If not, when should I call it?

Searchable Dictionary V2 Sample How to Perform rawQuery on the Dictionary Database?

I would like to perform a rawQuery on the dictionary database inside the method protected void onCreate(Bundle savedInstanceState) in WordActivity.java
It should be something like db.rawQuery() but I can't figure how to find the db instance inside the method...
Create your database helper class extending SQLiteOpenHelper
create instance of your helper passing the context from your activity and start accessing database with getWritableDatabase() API which gives you SQLiteDatabase instance where you can execute rawQuery

Addressing multiple instances of SQLiteOpenHelper when there are multiple Content Providers for a single database

In my app, I have implemented multiple content providers for a single db, one per table, as there are a lot of tables and having the logic of all of them in a single content provider is going to be quite messy.
I followed the advice given by Simo in this link:
Content provider for multiple tables
So there is an abstract AbsShopContentProvider that has a SQLiteOpenHelper member variable. This abstract content provider is then extended by multiple content providers like Table1Provider, Table2Provider,...
So now I have one instance of my SQLiteOpenHelper per Content Provider. Will this create any issues regarding thread safety?
Is it a good idea to make this SQLiteOpenhelper variable "static" in my abstract Content Provider and create an instance of it in onCreate() of the Abstract Provider only if it is null? Will it solve the issue of having many DB helper objects?
All you need is to make sure that you share one instance of SQLiteDatabase , SQLite automatically takes care of locking for same database.
To make a database globally available, extend Application class:
public class App extends Application {
private static SQLiteDatabase db;
public static SQLiteDatabase getDb() {
return db;
}
#Override
public void onCreate() {
super.onCreate();
db = new MySQLiteOpenHelper(getApplicationContext()).getWritableDatabase();
}
}
and add it to manifest:
<application
android:name=".App"
Now, you can access the database from any Activity/Fragment/Service by calling App.getDb()

Creating data model class for database handling

I was just starting to work on an database application when I realized I should implement MVC pattern as the application is quite complex and involves a number of database operations.
In regards to this, I have decided to create a separate model class for handling database operations. This class will have all methods which will return me the data after executing Sqlite command(Select for instance) OR will simply execute the SQLite command(Delete for instance). But what I want is to separate this class from Database Adapter class, where I open, create and close my database.
Let me put my concept into code :
public class DataModel
{
/*
Private members
*/
// Method to Select data from Student table
public ArrayList<String> FetchStudents (parameter 1)
{
private ArrayList<String> arrStudent;
DatabaseAdapter objDB= new DatabaseAdapter();
objDB.open();
/*
Some code
*/
objDB.close();
return arrStudent
}
//Method to delete record from Student table
public DeleteStudent(parameter 1)
{
DatabaseAdapter objDB= new DatabaseAdapter();
objDB.open();
//Some code
objDB.close();
}
/*
Rest of methods
*/
}
//DatabaseAdapterClass
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* onCreate method is called for the 1st time when database doesn't exists.
*/
#Override
public void onCreate(SQLiteDatabase db) {
Log.i(TAG, "Creating DataBase: " + CREATE_STUDENT_TABLE);
db.execSQL(CREATE_STUDENT_TABLE);
}
/**
* onUpgrade method is called when database version changes.
*/
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion);
}
}
Question:
What I want to ask is this the correct approach of implementation? Is it fine if create separate class for database methods? What limitations or issues you guys think might trouble me later on? Also, is there a better way to implement the above concept?
Thanks
Stone
What you are referring to as a 'model class' is more commonly known as a data access object (DAO). Your model would usually be a set of classes that hold your data and business logic. In you case, probably a Student class having an ID, name, GPA, etc. properties. If you want to separate data access from your model, you would have your data access class (DatabaseHelper) query the database and use the data it gets to return Student objects or a List<Student>. There is really not much point in separating the data access class from the database helper, it is better to have all of your database-related code in one place.
Using model classes (only), however, may not always be practical on Android, because it has native support for getting and displaying data from a Cursor (CursorAdapter, etc.). If you want to use any of that, you would have to expose your data not as model objects but as Cursor's. As for content providers, have a look at those too, but if you don't need to expose your data to other applications, writing a ContentProvider might be overkill.
On another note, you don't want to be opening and closing the database on each query. It is actually safe to leave it open, it will be automatically closed when your app's process dies.
I do this in my application and it works wonderfully, the code is clean and it doesnt impact performance at all, especially with the hardware phones have today. I tried all of the other approaches and even used a content provider but it just over complicated things in my opinion.
android's native approach data modeling is contentproviders. Link
it kind of abstracts the type of data source as well.
i used to do it in a similar way. but again its also subjective.

Categories

Resources