I am using Ormlite and I have an object that has a foreign field.
The said object also has getters and setters for it's fields.
public class Object {
#DatabaseField(foreign = true)
private Object2 foreignField;
Object() {
}
public Object2 getForeignField(){ return foreignField; }
public void setForeignField(Object2 foreignField){
this.foreignField = foreignField;
}
}
So I assumed that when I call :
Object testObject;
Object2 testObject2;
testObject.setForeignField(testObject2);
getDao.update(testObject);
It will automatically update the testObject in the database with the new foreignfield's id, but my table is not updating.
What am I doing wrong?
EDIT :
By reading the actual documentation on Ormlite, the update(Object) method will not update any foreign objects or foreign collections.
http://ormlite.com/javadoc/ormlite-core/com/j256/ormlite/dao/Dao.html#update(T)
NOTE: This will not save changes made to foreign objects or to foreign collections.
And now because of that, how do I update a foreign object on a table?
It will automatically update the testObject in the database with the new foreignfield's id, but my table is not updating.
It certainly should be.
The update(...) call doesn't compare the object with the database so a SQL UPDATE statement will be made. Have you tried turning on ORMLite logging?
If it is updating the Object with the same id from the Object2 foreignField then maybe that id is the same? When you call testObject.setForeignField(testObject2), the testObject2 should already have been created in the Object2 table. It needs to have an appropriate id field which is was gets stored in the Object table.
If you provide more details about the id field values and what the database has before and after the update, I may be able to help more.
Related
I have this OColumn partner_name = new OColumn("Partner", OVarchar.class).setLocalColumn(); in my sale order model class with odoo functional method that depends on partner_id column. I would like to search the partner_name in my list using that column partner_name, but I'm a little confused on how to achieve this. Please needed some help.
This is what I've tried:
BaseFragment
#Override
public void onViewBind(View view, Cursor cursor, ODataRow row) {
getPartnerIds(row);
OControls.setText(view, R.id.partner_name, row.getString("partner_name")); // displays false
....
}
}
private void getPartnerIds(ODataRow row){
OValues oValues = new OValues();
oValues.put("partner_id", row.get("partner_id"));
saleOrder.storeManyToOne(oValues);
}
updated:
I noticed that even though I created
#Odoo.Functional(method = "storeManyToOne", store = true, depends = {"partner_id"})
OColumn partner_name = new OColumn("Partner", OVarchar.class).setLocalColumn();
no column was created.
Updated:
partner_name column with odoo functional
Edit: Just place the 'if (type.isAssignableFrom(Odoo.Functional.class)'
before the 'if (type.getDeclaringClass().isAssignableFrom(Odoo.api.class))' to have the correct values.
Define the partner_name field like below:
#Odoo.Functional(method="storePartnerName", store=true, depends={"partner_id"})
OColumn partner_name = new OColumn("Partner name", OVarchar.class)
.setLocalColumn();
public String storePartnerName(OValues values) {
try {
if (!values.getString("partner_id").equals("false")) {
JSONArray partner_id = new JSONArray(values.getString("partner_id"));
return partner_id.getString(1);
}
} catch (Exception e) {
e.printStackTrace();
}
return "false";
}
You can simply get the partner_name using:
row.getString("partner_name")
EDIT:
Note that database is created when you first time run your application, or when you clean your data from app
setting. You need to clean application data everytime when you update your database column.
If the column was added after the database creation, it will not be added to the corresponding table. This is because the database is not upgraded. To fix this issue you can:
Clean application data to update your database column
Remove user account (This will delete database) or reinstall the application to recreate the database.
Or you can change DATABASE_VERSION in odoo/datas/OConstants then override onModelUpgrade method in sale order model and upgrade the table manually (alter sale order table and add the partner name column using SQL query: ALTER TABLE sale_order ADD partner_name VARCHAR(100)).
When a new sale order is created and synchronized, the partner name should be computed and stored automaticaly.
I noticed that the partner name was not set for existing records after synchrinization so I added another SQL query to compute and set the value of partner name for old records.
Example:
#Override
public void onModelUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("ALTER TABLE sale_order ADD partner_name VARCHAR(100)");
db.execSQL("UPDATE sale_order SET partner_name = (SELECT name from res_partner WHERE _id=partner_id) WHERE partner_name IS NULL AND partner_id IS NOT NULL");
}
Edit (config):
using the new configuration you will get the following error (which will prevent creating fields using annotations):
W/System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Class.isAssignableFrom(java.lang.Class)' on a null object reference
W/System.err: at com.odoo.core.orm.OModel.compatibleField(OModel.java:349)
CODE:
if (type.getDeclaringClass().isAssignableFrom(Odoo.api.class)) {
Try to remove .getDeclaringClass()
Edit: not all partner names are shown
There is a org.json.JSONException error that happens when it try to convert partner_id string to a JSON array.
W/System.err: org.json.JSONException: Unterminated array at character 12 of [114.0, UH PARTNER]
The error happens when it try to convert names containing spaces. To avoid that you can cast partner_id string to a list of objects.
In partnerName method, replace the following code:
JSONArray partner_id = new JSONArray(values.getString("partner_id"));
return partner_id.getString(1);
With:
List<Object> partner_id = (ArrayList<Object>) values.get("partner_id");
return partner_id.get(1) + "";
I have the following denormalized data structure:
A Contact can associate with multiple Records. A Record can have multiple associated Contacts (many<->many relationship). To keep track of their relationship, an int value to indicates the contact's role in a particular record, and store the role value in two separate references
Contact
- Contact1:data
- Contact2:data
- Contact3:data
Record
- Record1:data
- Record2:data
Record_Role_Ref
- Record1
-- Contact1: roleA
-- Contact2: roleA
-- Contact3: roleD
- Record2
-- Contact1: roleB
Contact_Role_Ref
- Contact1
-- Record1: roleA
-- Record2: roleB
I'm using FirebaseIndexRecyclerAdapter is to show a list of associated Contacts to a particular Record id. So for the key reference I would use Record_Role_Ref/record_id, and for the data reference I would use Contact, like so:
// Setup the reference to the all the associated contact list in record_role_ref, using the record id as key
Query mRecordRoleRef = firebaseDatabase.getReference().child(DB_RECORD_ROLE_REF).child(mRecordId);
// Reference the Contact data ref
Query mContactRef = firebaseDatabase.getReference().child(DB_CONTACT);
FirebaseIndexRecyclerAdapter mContactAdapter = new FirebaseIndexRecyclerAdapter<Contact, ContactViewHolder>(Contact.class,
R.layout.item_contact,
ContactViewHolder.class,
mRecordRoleRef, // The Firebase database location containing the keys associated contacts to this record
mContactRef)// The Firebase database location to watch for data changes. Each key key found at keyRef's location represents a list item in the RecyclerView.
Limitation(s): I don't want to store the role value in each contact and record object because each time a role is changed, both the contact and record's entire object would have fetched and updated. Users want to delete, modify, move both contact and records, and change roles.
Problem(s):
The contact's role value is stored as value of the key in the mRecordRoleRef. Is it possible/how to get the value from the key reference in on-go with FirebaseIndexRecyclerAdapter? What is the good/best practice in this kind of situation?
Thanks In Advance :)
As of now, I just form another data read request inside the populateViewHolder callback method. Since the data read request is itself also async, I'm not yet sure if this would work for a large list and when the view recycles. The viewHolder returned by the populateViewHolder is set to final.
Query mRecordContactRoleRef = firebaseDatabase.getReference().child(DB_RECORD_CONTACT_ROLE_REF).child(mRecordId).child(mContact.getContactId());
mRecordContactRoleRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Getting the role int base on record type
Long roleNum = (Long) dataSnapshot.getValue();
viewHolder.setContactRoleTv("hi, the role is " + roleNum);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I want to add an Attachment entity which I will be refering to from multiple different Entities, but it does not refer back to these, how do I get this working in ORMLite?
I keep getting this Exception:
Caused by: java.sql.SQLException: Foreign collection class entity.Attachment for
field 'attachments' column-name does not contain a foreign field named
'attachmentId' of class enity.News
For example I have a News Entity
#DatabaseTable
public class News extends Record {
#DatabaseField(index = true, id = true)
private long newsArticleId;
#DatabaseField
private String subject;
#DatabaseField
private String content;
#ForeignCollectionField
Collection<Attachment> attachments;
}
The Attachment Entity:
#DatabaseTable
public class Attachment extends Record {
#DatabaseField(id = true, index = true)
private long attachmentId;
#DatabaseField
private String attachmentUrl;
}
Could someone please point to me and laugh and tell me why I am doing this wrong and what I'm misunderstanding here. Thanks.
This is a FAQ. To quote from the ORMLite docs on foreign-collections:
Remember that when you have a ForeignCollection field, the class in the collection must (in this example Order) must have a foreign field for the class that has the collection (in this example Account). If Account has a foreign collection of Orders, then Order must have an Account foreign field. It is required so ORMLite can find the orders that match a particular account.
In your example, for ORMLite to figure out which Attachments a particular News entity has, the Attachment entity must have a News field. The other way to do would be to have a join table, but ORMLite won't do that for you.
Is there an elegant way to add a batch of new objects from JSON, taking into consideration that the new bunch might contain values that already in DB and that DB must contain only unique values?
Why not using the same id in the JSON object?, check that a unique id is being sent from the server and prepare a method that checks out for the id if it exists.
//Check if item exists already with id
public boolean checkIfExists(String id){
RealmQuery<Data> query = realm.where(Data.class)
.equalTo("id", id);
return query.count() != 0;
}
If i have for example a table Shows and i have a to-many relation to a table Actors
When inserting a Show which doesn't have id(its auto-generated), how can i insert Actors if i don't have id of the show to relate to?
Here is DaoGenerator code:
Entity show = schema.addEntity("Show");
show.setHasKeepSections(true);
show.addIdProperty();
show.addIntProperty("tvdb_id").notNull();
show.addStringProperty("title");
show.addIntProperty("year");
show.addStringProperty("url");
show.addLongProperty("first_aired");
show.addStringProperty("country");
show.addStringProperty("overview");
show.addIntProperty("runtime");
show.addStringProperty("status");
show.addStringProperty("network");
show.addStringProperty("air_day");
show.addStringProperty("air_time");
show.addStringProperty("certification");
show.addStringProperty("imdb_id");
show.addIntProperty("tvrage_id");
show.addLongProperty("last_updated");
show.addIntProperty("rating");
show.addIntProperty("votes");
show.addIntProperty("loved");
show.addIntProperty("hated");
Entity actor = schema.addEntity("Actor");
actor.addIdProperty();
actor.addStringProperty("name");
actor.addStringProperty("character");
actor.addStringProperty("image");
Property showId = actor.addLongProperty("show_id").notNull().getProperty();
ToMany showToActor= show.addToMany(actor, showId);
showToActor.setName("actors");
The ID is auto-generated when you insert the object.
So you have to insert the show before adding actors to it.
You can just call refresh() on that entity, the current copy would get updated and so its id.
Then you should take this showId and set it to each actor's show id.
show.refresh();
for (Actor actor : actors)
actor.setShowId(show.getId());
actorDao.insertAllInTx(actors);