I'm using try catch like below code to avoid crash app when using database query :
AppExecutors.getsInstance().diskIO().execute(()->{
try{
database.classDao().insertClass(new ClassEntry(className,classDay));
}catch(SQLiteException e){
Log.e("TAG","saveClassToDatabase: " +e.getMessage());
}
}
But I have many queries like this in my app and that means to I have to use many try catch.
My question : Is there a way to write try catch once and use it everywhere to handle queries error ?
Note : I use room database.
Using try/catch and possibly finally should be not be needed that much, if at all, when using Room as:-
@Insert(onConflict = OnConflictStrategy.IGNORE), will ignore NOT NULL, CHECK (not really applicable to Room) and UNIQUE constraint conflicts.long insert(TheObjectType the object);where the long returned will be the rowid (positive) if the row was inserted or -1 if not (an exception would be if forcing -1 as a value).int delete(TheObjectType object)where the value returned will be the number of affected rows, so if 0 nothing was deleted. Same for update except obviously 0 = nothing updated.Note that the onConflict action (IGNORE as above) does not apply to Foreign Key constraints if used. These are perhaps a potential for using catch/try although checks could be undertaken prior to insertion (deletion and updates can maintain the referential integrity automatically using
onDelete = ForeignKey.CASCADEandonUpdate = ForeignKey.CASCADErespectively).If you really need to have a single catch/try then you could not utilise Room's convenience methods (
@Insert, '@Update', '@Delete' and@Querybut instead use (although many would say misuse)@RawQuerythis is not a recommendation.Perhaps consider this demo which covers some of the above:-
The
@Entityannotated class School:-an
@Daoannotated class AllDao :-@RawQuerysan
@Databaseannotated abstract class TheDatabase :-Finally the activity code that demonstrates much that has been said above (not all though) in the answer; MainActivity :-
Results
As can be seen the first Stage insert 2 rows and the third was IGNORED and that no exceptions were encountered.
The second stage attempted to insert 4 rows using the
actionRawQuerymethod (a single try/catch). Thus 2 duplicate attempts one shows theOR IGNORE(what Room codes whenonConflict = OnConflictStategy.IGNOREis coded). The second duplicate, becauseOR IGNOREis not coded, results in a trapped/caught exception.The following is 2 other uses of
@RawQuerythat retrieves the database version (user_version) using thePRAGMA user_version. The first returns the result as a Cursor the second as a long.Additional
It would be possible to extend the relatively simple actionRawQuery method so that it can handle multiple queries. For example:-
First a new class RawQuery :-
An array of these could then be actioned by a new method such as actionMultipleRawQueries
To test/demonstrate the above, then Adding the following code to the activity:-
results in the log additionally containing:-
As can be seen the first use of actionMultipleQueries, as expected, trapped the exception due to the UNIQUE constraint and the resultant exception.
Whilst the second use due to using
OR IGNOREcompleted successfully.The third use shows the flexibility by
deleting Schools with an id that is an odd number, leaving only schools with even id's.
inserts a new School named school100 with an id of 100 and does so successfully, then
tries to insert a new school also named school100 but with an id of 1100, as
OR IGNOREis used the duplicate is ignored.finally updating even number schools to prefix the school name with NEW-
The results should be obtainable, at least for those that store the RawQuery[] in a variable rather than building it on the fly (as per the last/third use).
Again, this is not a recommended approach, rather it just demonstrates that you could "use try/catch purposefully"