When I try to add multiple records, via
#Insert(onConflict = OnConflictStrategy.IGNORE)
void insertAll(List<T> obj);
if one of the records has unique constraint error, it fails to insert the other record in the list as well.
Can't use the REPLACE on conflict, because it will cascade my previously created related table records.
I just need to insert multiple records, and if something is repeated, ignore that only. And keep adding the other records in the List.
There was a different issue. When I looked for MyTableDao_Impl.java, I realised, for each record in the list, there is a different insert transaction.
And OnConflictStrategy.IGNORE ignores the current transaction only. So clearly this can't be the issue.
Related
I have a Room table of objects and when I get my network call to refresh the list of objects the items could have been changed. So I need to remove any data that is no longer in the new fetched list.
Pre-Fetch Ids in Table:
|ObjectId|
|:-------|
|1|
|2|
|3|
|4|
Post-Fetch Ids in Table:
|ObjectId|
|:-------|
|1|
|2|
|4|
So Objects removed:
|ObjectId|
|:-------|
|3|
My Quesiton: Is the best way to do this just Delete all entries in the table before calling an #insert method or is there another way using the #update that will allow me to simply fetch the new data and remove all the old data that is no longer in the new list of objects? My understanding is that an #update will simply update objects 1,2 & 4 and leave 3 as it was.
As you have a list of id's (assuming these uniquely identify the rows) then you could update according to the list and delete (before or after the updates) according to the list using a WHERE clause that utilises NOT IN operator(s)
Note that the deletion should be done via an #Query not #Delete e.g. #QUERY("DELETE FROM the_table WHERE id NOT IN(:the_id_list);"
This would minimise the number of deletions. Deletiong and Updates should be done within a single transaction.
which is faster:
to delete records each one at a time
e.g. listOfObjects.forEach{ repository.delete(it.id) }
and here is the query
#Query("DELETE FROM myTable WHERE object_id=:id")
fun delete(objectId: Long)
2. to delete the whole list in a single query
e.g. repository.delete(listOfObjectIds)
and here is the query
#Query("DELETE FROM myTable WHERE object_id=:id in(:objectIds)")
fun delete(ObjectIds: List<Long>)
?
By far, the second list version will outperform the first version, which issues N delete statements for a list of size N. The main reason is that the second version requires only one round trip to and from your SQLite database, while the first version requires N trips.
In addition, the second version has the added benefit that your entire logical delete operation can execute within a single transaction. The first version would, by default, execute across multiple transactions. This could lead to potential problems should, for example, an exception occur halfway through the batch of single delete operations.
I am trying to implement a Room database using a one-to-many relation, following the Android Room training (https://developer.android.com/training/data-storage/room/relationships#one-to-many).
However, I can't find a way to add a condition on the second table.
For example, to fetch all UserWithPlaylists, for users above 25 and having playlists names starting with "play" this does not work because Room does not automatically group the results (and a GROUP BY clause prevents creating the List of Playlist):
#Transaction
#Query("SELECT User.* FROM User, Playlist WHERE User.age > 25 AND Playlist.playlistName LIKE play%")
public List<UserWithPlaylists> getUsersWithPlaylistsSpecific();
I already tried solutions such as embedding one entity in another and using
#Embedded(prefix = "PETS_")
as suggested here: https://stackoverflow.com/a/50698610 but without success.
I also want to avoid this method using a Java Map.
How can I achieve this?
I am creating an app which needs to show events based on date and time. I imagine it something like this:
For each date, I have time, each of which has something inside. Based on previous project, I started implementation with Room. However I got stuck on my first query with the error that my primary key is not unique. Which makes sense, since am I using #Insert which will add new row with the same ID (the date). How should I organize the DB, so I can have something like the above picture?
How can I get the the first row from first table and add underneath?
Or I should use JSON instead, since my DB won't be that big (I can store in JSONs per month).
I am working on an android application using android:minSdkVersion="14". The application receives data as JSON from a server. The data received need to be added to an sqlite table. If a row exists, all fields except for two have to be updated. If a row does not already exist in the table, it has to be inserted. I am looking for the most efficient way as regards performance.
The function insertwithonCoflict() has been considered but it is not an option since in case of update, it updates all the fields including the two that should not be updated.
The function replace() is also not suitable.
I would opt for a SELECT to check if the row exists and then an INSERT or UPDATE but I was wondering if I could optimize the procedure somehow .
Two approaches:
Change the database structure so that the table has only the server data. Put local data (the two columns) in another table that references the server data table. When updating, just insert to the server data table with "replace" conflict resolution.
Do the select-insert/update logic.
For performance in any case, use database transactions to reduce I/O. That is, wrap the database update loop in a transaction and only commit it when you've done with everything. (In case the transaction becomes too large, split the loop into transaction chunks of maybe a few thousand rows.)
A nice solution I use is as follows:
long id = db.insertWithOnConflict(TABLE, null, contentValues, SQLiteDatabase.CONFLICT_IGNORE);
if(id!=-1) db.update(TABLE, contentValues, "_id=?", new String[]{String.valueOf(id)});
This ensures the row exists and has the latest values.