Transactions in GreenDao - android

I'm using GreenDao to store a lot of data, coming from a REST service.
A lot of my entities are connected with relations.
Everything works great, but tomorrow I have to implement a rocksolid workflow.
When I load my data I have to check if an error occurs.
If so, I have to make sure nothing is stored in the SQLite DB.
Normally I would work with transactions and rollback in case of an exception,
otherwise commit to the db.
For now I just use insertordelete to save an entity, everytime I created an object.
What would be the way to implement this?

On inserts and updates Greendao checks if there is a ongoing transaction. If that is the case greendao will not start a new transaction.
So the only thing to do is to start a transaction on your database and commit/rollback after your work is done or you notice an error. All inserts and updates will be in the same transaction which has benefits concerning data consistency and also on performance, since greendao will start new transactions with commit/rollback for every insert and update operation.
Summarized you can use code like this:
SQLiteDatabase db = dao.getDatabase();
db.beginTransaction();
try {
// do all your inserts and so on here.
db.setTransactionSuccessful();
} catch (Exception ex) {
} finally {
db.endTransaction();
}
I also tweaked my greendao a bit so that it doesn't cache inserted objects to get further performance and memoryusage benefits (since I insert a lot of data once and I only use very few data during runtime depending on user input). See this post.

Related

Firestore transaction billing rules

I'm new in Android and Firestore. Im currently making an app that uses Cloud Firestore. In my transaction I have one read (transaction.get()) and one write (transaction.set()) operation. I've noticed that in usage tab in Firebase Console, this transaction increments read counter by 1, but write counter increments by 2. I have removed transaction.set operation for testing, and with transaction.get operation only, this whole transaction still increments write counter by 1. Is it normal? Are those normal rules for billing transactions in firestore? I don't know if it matters that reading and writing is done to different files in Cloud Firestore.
db.runTransaction(new Transaction.Function<Object>() {
#Nullable
#Override
public Object apply(#NonNull Transaction transaction) throws FirebaseFirestoreException {
DocumentSnapshot snapshot = transaction.get(carReference);
.
.
.
transaction.set(pointReference, point);
return null;
}
});
According to the Official Documentation, You are charged for each document read, write, and delete that you perform with Cloud Firestore.
In your case, I am not able to see why the write is incremented by 2 the first time you write. Maybe you are writing something else in the code.
But regarding the reads, it's an expected behavior because when you listen to the results of a query, you are charged for a read each time a document in the result set is added or updated. And in your case, as you are setting, so the second time, the read is incremented by 1.

Android Room requery on db change

I'm writing an application using newest Room Persistance Library.
The app sipmply shows a list of items and updates this list as data changes.
When new item is inserted into a table, or updated, I expect the list to update automaticlally.
I tried vanilla LiveData and Flowable so far. Both are claimed to support this feature, as it is stated in documentation and on this blog:
https://medium.com/google-developers/room-rxjava-acb0cd4f3757
Here's the ViewModel snippet in Kotlin:
messagesFlowable = db.messagesDao().all()
messagesFlowable
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
Log.d(TAG, "Received 1 list of %s items", it.size)
messages.value = it
}
Somewhere else, the db is modified like this:
mDb.messagesDao().add(Message("Some data"))
The updates are not pushed to observers. I guess I'm missing something, but what?
Update: This problem is solved and the answer is below.
I'll answer my own question, as the solution is not documented.
It looks like you need to have the same instance of database object.
In my case, my Dagger2 was misconfigured to inject new instances of DB each time, so my Repository and ViewModel ended up with 2 separate instances.
Once I use single database instance shared among all interested parties, all updates are distributed correctly.

GreenDao reload an object when using IdentityScope != None

I have the case that I operate on some object I got from greenDao and in some cases I have to revert the changes. I only got this to work with IdentityScope.None - with some IdentityScope I found no way to do that - even refresh() which sounded promising was not bringing back the data from the database. Is there any way to do this with a IdentityScope?
The refresh(entity) method of a DAO does reload all entity values from the database. However, it operates on a single entity, not on a tree of entities.

Multiple threading questions when using sqlite transaction in Android

I use sqlite transaction in Android:
SQLiteDatabase database = sqlite_helper.getWritableDatabase();
database.beginTransaction();
...
database.setTransactionSuccessful();
database.endTransaction();
My questions are :
1. Should I place endTransaction() in finally code block like this:
try {
database.beginTransaction();
...
database.setTransactionSuccessful();
}
finally {
database.endTransaction();
}
If there are exepctions during database operations, will the database be rolled back automatically without using "finally"?
When the transaction is not ended, can other threads read or write the same database? I hear sqlite in Android is threading safe, but I are not sure with it. I guess there will be some problems during transaction. Is there an error raised if another thread writes the same database with the same connection?
I ever found this error in my app, but I don't know whether it's related to the threading safe problem:
android.database.sqlite.SQLiteMisuseException: library routine called out of sequence:
, while compiling
Does anyone help me to answer these questions? Thanks a lot!
1.you should always place endTransaction in finally block
2.transaction in SQLite is thread safe,see the doc http://www.sqlite.org/atomiccommit.html
You should always put endTransaction() into a finally block (also see the docs).
Otherwise, the database would not be able to notice than an exception has happened.
The only other way to end a transaction would be to close the connection, in which case SQLite automatically rolls back any active transaction.
As long as one connection writes to the database (which means that a transaction is active), no other connections can read or write. Therefore, you should take care not to forget to end transactions.
You should never write from multiple threads; what would happen if one threads ends the transaction while the other one is still writing?
Your SQLiteMisuseException might be related, or not; that's impossible to say without seeing the code.
Yes, you should use the finally block. Here is a simple, THREAD SAFE method I use:
/**
* Call for multiple DB insertion transactions. It is thread safe and fast!
*/
private synchronized void writeTransaction(Runnable task) {
try {
db.beginTransaction();
task.run();
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
the synchronized keyword locks the method with its containing object, thus making it thread safe...

greendao delete from db and session

I'm using greendao for a android project and wanted to know how to properly delete and object from the db and from the session cache. Currently I do the following to delete from the db:
ChatDao chatDao = daoSession.getChatDao();
chatDao.queryBuilder().buildDelete().executeDeleteWithoutDetachingEntities();
However as the method name and documentation state this may leave stale objects in the session cache, how can I remove the objects from there too?
In order to clear cached objects in your DaoSession use this call:
DaoSession.clear();
It will clear all objects in your session identity scope.
As Anatoliy described, you can use DaoSession.clear(). However, it will clear all all objects from the session. If you want to avoid that, you have to execute a regular query and delete the result entities (for example with deleteInTx).

Categories

Resources