I have a relation: an order contains many order-items. I'd like to insert it a single statement rather than: inserting order, obtaining generated order id, setting order-id for every order-item and finally inserting order-items.
For instance:
Order newOrder = new Order();
o.setItems(orderItems);
o.insert();
instead of:
Order newOrder = new Order();
newOrder.insert();
foreach orderItems : orderItem.setOrderId(newOrder.getId());
orderItems.insert();
Thanks.
greenDAO does not support this.
Updating lists of related entities is not trivial because items could be added, updated, or deleted. greenDAO is not Hibernate, so you need to do those things manually.
Related
I want to insert list of objects into my SQLite db. If I do query for each object to check if its present, it takes alot of time for long list (20-30sec).
I used function 'insertWithOnConflict()' to do that faster.
I thought that it will try to insert a row and if record with same value of column entered to function already exists, it will just replace its values (like update) otherwise it will insert new row.
But I checked my DB and it is creating duplicated objects. Any solution for this?
Important information 'COLUMN_OBJECT_ID' is not 'PRIMARY_KEY'. 'PRIMARY_KEY' is autoincrement. But 'COLUMN_OBJECT_ID' has to be unique in this case. So I want to update row with same 'COLUMN_OBJECT_ID' because data inside can change.
Code:
fun saveObjectsToCache(objects: List<Item>) {
val db = getDb()
db.transaction {
objects.forEach {item->
val cv = ContentValues()
cv.apply {
put(COLUMN_OBJECT_ID, item.id)
put(COLUMN_OBJECT_DATA, item.js.toString())
}
insertWithOnConflict(TABLE_OBJECT_CACHE, COLUMN_OBJECT_ID, cv, SQLiteDatabase.CONFLICT_REPLACE)
}
}
}
Looks like you forgot to add a unique constraint on COLUMN_OBJECT_ID.
Because of this, there is no conflict when you add a row with the same COLUMN_OBJECT_ID.
Make COLUMN_OBJECT_ID unique and it should work.
Additionally, if COLUMN_OBJECT_ID is unique, and is what you use for checking existing values in the table, you should probably make it the primary key, instead of the auto increment one you are using right now as the primary key.
It will be more efficient both in memory usage, and in performance
I am working on Room database and trying to insert list of items(eg. list of Quotes which contains author name and a quote in my case).
Following is the code I am using:
// view model
BaseApp.daoInstance?.appDao()?.insertQuotes(response!!)
// dao
#Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertQuotes(listData: MutableList<Quote>)
When I try to insert the same data again, it always inserts as a new data instead of replacing with the current items.
I have researched a lot for this OnConflictStrategy.REPLACE but could not find any proper answer.
Is there anyone facing the same issue and found solution or am I doing anything wrong?
Thank you in advance...!!!
Room, will not check and compare if you have the quote already in the DB.
What it will do is look if the primary key already exists in the DB if it does, Room will replace all old data with the new one.
In your case, you are not specifying an ID so the DB is generating a unique one for you.
What you should do is create a Query that will search for this quote in the DB something like this:
#Query("SELECT * from quote_table WHERE author = :author AND quote = :quote")
List<Quote> getQuoteByAuthorAndQuote(string author, string quote);
This should return a list with a single quote if one is found and empty if it does not exist.
If you would like to override the old one just update the data in the Quote POJO and insert it to the DB using Room.
Have you tried to index your main column and mark it as unique?
#Index(value = {"quote"}, unique = true)}
It suppose to search for your unique or primary key and compare then replace, while in your case you're not defining an ID so it will generate a unique one for you, so it won't even compare and will consider any item as a new one.
Write a new query and function to solve this issue.
When I had same problem, changes in imports did the trick, added following import:
import androidx.room.*;
I'm using ORMLite but when I do prints after deletes for exemple I still see the deleted lines, for exemple:
demandesDao = db.getDemandesDao();
final List<Demandes> demandes = demandesDao.queryForAll();
DeleteBuilder<Demandes,Integer> deleteBuilder = demandesDao.deleteBuilder();
deleteBuilder.where().eq("contactWebId", 15515);
deleteBuilder.delete();
System.out.println(demandes);
I'm using ORMLite but when I do prints after deletes for example I still see the deleted lines
That's correct. The DeleteBuilder only removes rows from the database. Any local collections that you have already queried for are not affected. In your case, your demandes list was queried before the delete was performed. If you run another queryForAll() method, you should see that the rows have been removed from the database.
I'm new to app development using SQLite and Sugar ORM on Android, and have tried to read through the Sugar ORM documentation, but didn't find anything for how to update a saved object in SQLite. Can I still save the object after changing its properties? something like:
Customer myCustomer = (Customer.find(Customer.class, "id = ?", id)).get(0);
myCustomer.setName("new name");
myCustomer.setAddress("new Address");
myCustomer.save(); // is this okay for updating the object?
the save() method won't create another new object while leaving the old entry untouched, right?
Your code should update the row without issue.
From the docs - Update Entity:
Book book = Book.findById(Book.class, 1);
book.title = "updated title here"; // modify the values
book.edition = "3rd edition";
book.save(); // updates the previous entry with new values.
It will update your entity. The Sugar ORM overwriting your existing e.g Name and updated it with "new name" after the save() method call.
Updating a saved object is pretty straightforward.
Retrieve the object;
Object object= Object.findById(Object.class, ID);
Set the attributes you need to;
object.setAttr("new value");
Then finally call save;
object.save();
Alternatively, as someone mentioned above one can choose to use update() which works slightly differently and would ideally be used when changing several attributes;
First create the object and set the necessary attributes;
Object object= new Object();
object.setAttr("some data");
Then set an ID for the Object that ideally already exists in the database in order to target that item for replacement;
object.setID(ID);
And finally;
object.update();
Save and Object methods are completely different and both are really useful.
If you have an object and you say:
Object.save();
That will override all of the other fields as well for example:
column1 column2
1 1
if in your object you have only set column1 corresponding field a number like 2 you will get:
Object.save();
column1 column2
2 NULL
Object.update();
column1 column2
2 1
You don't need to use .setId() explicitly to get update working it looks for a unique item if it's found it will update that,if not it will create a new row.By default an auto increment ID column is added to each of your tables and used as unique ids for update.If you need your own fields to be unique use:
#Unique
String MyID
or for multiple of the same thing you can use:
#MultiUnique("MyFirstID,MySecondID")
public class MyClass extends SugarRecord {...
which both are name of your fields in the table.
I'm trying to think of how to get around this problem. I have an ORMlite object that can belong to multiple Categories; I'm using another table (i.e. a ForeignCollection) to track many-to-many connections between my objects and categories.
The problem is if I update the object with changed categories, the new categories are added, but old ones are not removed.
In the JavaDoc for the update method of DAO I see this text:
NOTE: Typically this will not save changes made to foreign objects or
to foreign collections.
My question is about the use of the word "typically." Does this mean that there IS a way through some sort of setting to make sure that updates update related foreign objects/collections?
Or should I read the sentence as if "typically" was not there, assume there is no automatic method, and that I need to run extra queries on committing each object to delete old categories?
The problem is if I update the object with changed categories, the new categories are added, but old ones are not removed.
So you have an object that has a foreign collection of categories:
#ForeignCollectionField
ForeignCollection<Category> categories;
If you run categories.add(category1) or categories.remove(category1), then the underlying collection should remove those from its associated table using a built-in DAO.
If you are changing the category list some other way then you are going to have to remove the Category entries by hand using the categoryDao directly.
... about the use of the word "typically." Does this mean that there IS a way through some sort of setting to make sure that updates update related foreign objects/collections?
Not sure why I left the word "typically" there. I think it was a blanket statement to take into account the various auto-create, auto-refresh, etc. field settings -- I'm not sure. In any case, I've removed it from the code base.
ORMLite has no way to know if foreign objects have been changed. It does not create magic proxy objects nor sessions so that it can tell when a foreign object has been updated. You have to be explicit about what you want updated when. The documentation on foreign collections is quite explicit about it.
OrmLite will not save objects to ForeignCollections automatically. You have to store and delete these objects yourself. Ormlite will retrieve the objects in the ForeignCollection automatically for you, provided you set the right parameters in the annotation.
Ormlite is "lite". It does ORM, but not completely. It's not JPA or Hibernate.
I solved this problem by adding the new Category to the table Categories directly, instead of adding a new category to the Object's foreignCollection.
This can be done by simply creating a category ado and adding a new element.
A newCategory.setObject(object) is needed in order to create the relation with the object.
Hope this helps.