Is there any way to get Cursor for a query, which I am processing with ORMLite Dao object?
ORMLite now supports next(), previous(), moveRelative(offset), ... methods on the CloseableIterator class. This should allow you to move the underlying Cursor object around at will.
It also supports the following DAO Cursor methods:
dao.mapSelectStarRow(databaseResults) Return the latest row from the database results from a query to select *. With this you can change the cursor location (for example) and then get the current object.
dao.getSelectStarRowMapper() Provides a mapper that you can use to map the object outside of the Dao.
When you are building your own query with ORMLite, you use the QueryBuilder object. queryBuilder.prepare() returns a PreparedQuery which is used by various methods in the DAO. You can call dao.iterator(preparedQuery) which will return a CloseableIterator which is used to iterate through the results. There is a iterator.getRawResults() to get access to the DatabaseResults class. Under Android, this can be cast to an AndroidDatabaseResults which has a getCursor() method on it to return the Android Cursor.
Something like the following code:
// build your query
QueryBuilder<Foo, String> qb = fooDao.queryBuilder();
qb.where()...;
// when you are done, prepare your query and build an iterator
CloseableIterator<Foo> iterator = dao.iterator(qb.prepare());
try {
// get the raw results which can be cast under Android
AndroidDatabaseResults results =
(AndroidDatabaseResults)iterator.getRawResults();
Cursor cursor = results.getRawCursor();
...
} finally {
iterator.closeQuietly();
}
This is a bit complicated but you are definitely having to peer behind the vale to get to this object which is hidden by the database abstraction classes.
Did you try some of Gray's advice from this post? He explains how you can select a column as another name, such as, select id as _id.
If you're in an Activity and don't want to mess around with the QueryBuilder give the following a go, which is just as effective.
Cursor cursor = getHelper().getReadableDatabase().query(tableName, projection, selection, selectionArgs, groupBy, having, sortOrder)
If you mean the getHelper() method to reach the dao methods create etc. you only have to inherit from the OrmLiteBaseActivity<YourDBHelper> and you can call it. It will look sth like this:
public class YourClass extends OrmLiteBaseActivity<YourDBHelper> {
#Override
protected void onCreate(Bundle savedInstanceState) {
...
getHelper().getDao().queryForAll();
...
}
}
If you mean the cursor to handle database operation: I don't think that you can reach it! But I don't understand why you should need it. ORMLite has nearly all functions of the cursor. So what do you need it for?
Related
I'm planning to use Android SQLite for the first time.
Cursor c = db.rawQuery("some select command here", null);
// some jobs with the cursor..
c = db.rawQuery("another select command here", null);
// some jobs with the cursor..
c.close();
db.close();
c = null;
db = null;
As you can see, I'm trying to call rawQuery() method several times.
Do I have to close the cursor before I call rawQuery() method AGAIN?
Do I have to assign null to the variables after closing the cursor and database like above?
Do I have to close the cursor before I call rawQuery() method AGAIN?
Close the cursor whenever you are finished reading from it. This is to release resources that are opened by the cursor, so yes, you should close the first cursor before the second query.
Do I have to assign null to the variables after closing the cursor and database like above?
It depends on the scope of the variables. If your code looks like this...
class Foo {
void doSomething() {
SQLiteDatabase db = ...
Cursor c = db.rawQuery...
// other stuff
c.close();
db.close();
}
}
... then there's really no point nulling them out because they will go out of scope immediately when the method finishes execution. But your actual code might look different. If you have some reason for wanting to allow those objects to be garbage collected, then you can null out the variables.
In my project i'm updating the searchtag in the database by using this query
public void updatesearchtag(){
SQLiteDBHelper sqLiteDBHelper = new SQLiteDBHelper(context.getApplicationContext());
Cursor crs=sqLiteDBHelper.getWritableDatabase().rawQuery("update shoply_coupon set searchTag=(Select SearchTag from shoply_retailer_master where retailerId=shoply_coupon.retailerID)",null);
//Cursor crs=sqLiteDBHelper.getWritableDatabase().execSQL("update shoply_coupon set searchTag=(Select SearchTag from shoply_retailer_master where retailerId=shoply_coupon.retailerID)");
}
but the query is not working may i know what error i'm doing over here
Use execSQL() and not rawQuery() for SQL like this.
rawQuery() just compiles the SQL but doesn't run it. It is only run when the cursor is moved. execSQL() both compiles and runs the SQL.
Also, use getWritableDatabase() and not getReadableDatabase() for updates.
Share your code please which you are using for updating . Also about the SearchTag values.
I will suggest to make the Dbclass seprate in your code and use the functions like this. this is a easy way to do every thing such as update,delete,select etc
public boolean Update(String SearchTag , ContentValues values)
{
if (db.update(TABLE, values, "SearchTag = '"+YourValue+"'", null) > 0)
{
return true ;
}
return false ;
}
Use
sqLiteDBHelper.getWritableDatabase()
instead
sqLiteDBHelper.getReadableDatabase()
Since you are trying to write into a database which is in write prevention mode.
I am using a rawQuery in my DB class and returning the cursor to my adapter which is a CursorAdapter which I use with a custom ListView item.
Is this cursor automatically closed after the view is painted in the screen or how to manage this cursor? what is the best practice in this scenario ?
If I close this cursor in DB class I am not able to access them from my adapter.
Thanks for your time and effort in helping me.
EDITing to add some code snippets for better understanding
This is my activity code:
calAdapter = new CalendarListAdapter(context, dbHelper.getAllCalendars());
drawerList.setAdapter(calAdapter);
This is my cursor
public Cursor getAllCalendars() {
String query = "SELECT calendarId as _id, calendarName, calState, calShow FROM "
+ TABLE_CALENDAR_LIST;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(query, null);
return cursor;
}
You can close the old cursor after you set the new one. swapCursor() returns the old Cursor, returns null if there was not a cursor set, also returns null if you try to swap the same instance of the previously set cursor. Knowing that, you can try something like this:
Cursor oldCursor = yourAdapter.swapCursor(newCursor);
if(oldCursor != null)
oldCursor.close();
Note that when you are using a Loader (LoaderManager.LoaderCallbacks), the framework is going to close the old cursor. This is what the documentation says:
onLoadFinished:
The loader will release the data once it knows the application is no
longer using it. For example, if the data is a cursor from a
CursorLoader, you should not call close() on it yourself. ...
Cursor does not get closed automatically. You need to close it. In older API you could register Cursor at Activity by calling Activity.startManagingCursor(). In this case Activity takes responsibility for managing it. In newer API you should better use LoaderManager.
I know I can use Cursor c=managedQuery(Contacts.CONTENT_URI,null,null,null,Contacts.DISPLAY_NAME+" ASC") to get a Cursor.
Now I hope to get a Cursor from myMRuleList, how can I do? Thanks!
lv = getListView();
Cursor c=managedQuery(Contacts.CONTENT_URI,null,null,null,Contacts.DISPLAY_NAME+" ASC");
String[] cols=new String[] {Contacts.DISPLAY_NAME};
int[] views=new int[]{android.R.id.text1};
SimpleCursorAdapter myAdapter=new SimpleCursorAdapter(this,android.R.layout.simple_list_item_1,c,cols,views);
this.setListAdapter(myAdapter);
List<MRule> myMRuleList=new ArrayList<MRule>;
MRule aMRule=new MRule();
aMRule.ruleID=1;
aMRule.name="a";
aMRule.enabled=false;
MRule bMRule=new MRule();
bMRule.ruleID=1;
bMRule.name="b";
bMRule.enabled=false;
myMRuleList.add(aMRule);
myMRuleList.add(bMRule);
public class MRule {
public int ruleID;
public String name;
public Boolean enabled;
}
You shouldn't create a Cursor from a List. If you want to insert/update the data on permanent storage you should use the insert() and update() provided by ContentResolver.insert()/update() or SQLiteOpenHelper.insert()/update() if dealing with ContentProviders or SQLite databases respectively
Cursors are typically used with table-like structures (ContentProviders/Databases) not Lists.
As zapl recommended you should avoid managedQuery() and use the Loader framework. By doing so, your queries will be done on a separate Thread.
Why would you do that? Is it to update your database or what do you want to achieve?
Here is the link to google's reference for the Cursor class:
http://developer.android.com/reference/android/database/Cursor.html
If you just want to update your database read this SO question:
How to properly insert values into the SQLite database using ContentProvider's insert() method through a CursorLoader?
android.database.MatrixCursor, is this what you want?
Right now, I'm running into issues trying to implement a FilterQueryProvider in my custom SimpleCursorAdapter, since I'm unsure of what to do in the FilterQueryProvider's runQuery function.
In other words, since the query that comprises my ListView basically gets the rowID, name, and a third column from my databases's table, I want to be able to filter the cursor based on the partial value of the name column.
However, I am uncertain of whether I can do this directly from runQuery without expanding my DB class since I want to filter the existing cursor, or will I have to create a new query function in my DB class that partially searches my name column, and if so, how would I go about creating the query statement while using the CharSequence constraint argument in runQuery?
I am also concerned about the performance issues associated with trying to run multiple queries based on partial text since the DB table in question has about 1300-1400 rows. In other words, would I run into a bottleneck trying to filter the cursor?
You need to run a query that will return a new filtered cursor:
public class MyActivity extends ListActivity implements FilterQueryProvider {
private Cursor cursor;
#Override
public Cursor runQuery(CharSequence constraint) {
if(cursor != null) {
cursor.close();
}
cursor = somehowGetAFilteredCursorFor(constraint);
startManagingCursor(cursor);
return cursor;
}
}