ORMLite foreign field null on create, not null on query - android

When writing an instance of my data class to the database via ORMLite, and one of the child members (a foreign field) is null, I get back a non null child member.
Data classes as follows:
public class Site {
// snip
#DatabaseField(foreign = true, canBeNull = true)
private InstallationType installationType;
}
public class InstallationType {
#DatabaseField(generatedId = true)
private int id;
#DatabaseField
private String name;
}
When I read my instance of the Site class again via
getSiteDao().queryForId(id);
the installationType member is non null, but with a non-existent id. The only way the rest of our application can now work with this object, is if I manually do a lookup through the InstallationTypeDAO and set what I get back on the site. Query will sometimes return null as per the documentation.
Is there a way of getting ORMLite to set this member to null?

This was a bug in ORMLite that was fixed in version 4.15 (3/7/2011). Here's the change log file. What version are you using? Have you tried to update? Here's the bug report page:
Currently the following test passes so I think we have good coverage on that bug.
#Test
public void testForeignNull() throws Exception {
Dao<Foreign, Integer> dao = createDao(Foreign.class, true);
Foreign foreign = new Foreign();
foreign.foo = null;
assertEquals(1, dao.create(foreign));
Foreign foreign2 = dao.queryForId(foreign.id);
assertNotNull(foreign2);
assertNull(foreign2.foo);
}
With Foreign having the following fields:
#DatabaseField(generatedId = true)
public int id;
#DatabaseField(foreign = true)
public Foo foo;
If you are up to date in versions, please let me know if you can change the test to get it to fail.

Related

How to make many-to-many relation query in GreenDAO with source property other than primary key?

Let's assume we have following entities:
Item:
class Item {
...
#Index(unique=true)
private String guid;
...
#ToMany
#JoinEntity(entity = JoinItemsWithTags.class, sourceProperty = "itemGuid", targetProperty = "tagName")
private List<Tag> tagsWithThisItem;
...
}
Tag:
class Tag {
#Id
private Long localId;
#Index(unique = true)
private String name;
...
}
and we need to join them. Here is my join entity class:
#Entity(nameInDb = "item_tag_relations")
class JoinItemsWithTags {
#Id
private Long id;
private String itemGuid;
private String tagName;
...
}
I want to use tag name as a join property instead of Long id, because it's easier to support consistency when syncing with server.
But currently tags getter in Item class always return an empty list. I've looked into log and found generated query which using internally in that getter:
SELECT * <<-- there were a long sequence of fields
FROM "tags" T JOIN item_tag_relations J1
ON T."_id"=J1."TAG_NAME" <<-- here is the problem, must be `T."NAME"=J1."TAG_NAME"`
WHERE J1."ITEM_GUID"=?
So the problem is that join is base on tag's _id field. Generated List<Tag> _queryItem_TagsWithThisItem(String itemGuid) method implicitly uses that id to make a join:
// this `join` nethod is overloaded and pass tag's id as source property
queryBuilder.join(JoinItemsWithTags.class, JoinItemsWithTagsDao.Properties.TagName)
.where(JoinItemsWithTagsDao.Properties.ItemGuid.eq(itemGuid));
Correct approach is this case might be following, I suppose:
// source property is passed explicitly
queryBuilder.join(/* Desired first parameter -->> */ TagDao.Properties.Name,
JoinItemsWithTags.class, JoinItemsWithTagsDao.Properties.TagName)
.where(JoinItemsWithTagsDao.Properties.ItemGuid.eq(itemGuid));
But this code is in generated dao, and I don't know how to do anything with it. Is there any way to workaround this?

ORMLite one-to-many relationship of itself

I have a model that has a one-to-many relationship of itself. Every time I run my android application, I keep getting an SQLException that states that my Foreign Collection class Route for my field childRoutes column-name does not contain a foreign field of class Route. I feel like I specified this already in my Model but I may be missing something?
Here is my model excluding the getters/setters:
public class Route implements Serializable{
#DatabaseField(id = true, canBeNull = false, columnName = "id")
private long id;
#DatabaseField(columnName = "parent", foreign = true)
private Route parent;
#ForeignCollectionField
private ForeignCollection<Route> childRoutes;
}
I followed this question here but I still can't seem to be getting it right.
ORMLITE one-to-many recursive relationship
I seemed to have solved the issue by replacing private ForeignCollection<Route> to just Collection<Route>. I'm not quite sure why it's not working if I use ForeignCollection as the type, but it seems to fix all my issues.

Implementing a SQLite Database with List<String> as Column type using ORMLite

I have a requirement where I need to store a List in a column in the database. Serializing the list might be an option, but i am not sure if it is the right one.
Also, i want to avoid creating another table to store the list elements and a reference to the original table row.
I am using ORMLite for the database operations.
Its a concept of foreign collection.
You need to create an entity that wraps the String. Something looks like:
#DatabaseTable
public class Student {
#DatabaseField(generatedId = true)
print int id;
#DatabaseField
private String fname;
#DatabaseField
private String lname;
#DatabaseField(foreign = true)
private Address address;
}
Then your Address class would have a ForeignCollection of these Student.
#DatabaseTable
public class Address {
#DatabaseField(generatedId = true)
print int id;
#ForeignCollectionField()
private ForeignCollection<Student> student;
}
Also refer this link , may it will help you.

Auto increment ID Insert Data ORMLITE

I'm new to Android and I have problem with ORMLITE.
For example let's say I have this table:
#DatabaseTable(tableName = "accounts")
public class Account {
#DatabaseField(id = true)
private int id;
#DatabaseField(canBeNull = false)
private String name;
…
and I want to add new data into my table without setting id.
I tried this way:
#DatabaseTable(tableName = "accounts")
public class Account {
#DatabaseField(generatedId = true,allowGeneratedIdInsert=true)
private int id;
#DatabaseField(canBeNull = false)
private String name;
…
> Account acc = new Account();
>
> acc.setName("Example");
>
> AccountDao.createOrupdate(acc);
Here I can't insert acc into my database because acc id is zero. I want to generate id. Can I use autoincrement?
Here i can't insert acc into my database because acc id is zero. I want to generate id. Can i use autoincrement ?
So to quote the javadocs for the allowGeneratedIdInsert field in #DatabaseField:
If this is set to true then inserting an object with the ID field already set will not override it with a generated-id. This is useful when you have a table where items sometimes have IDs and sometimes need them generated. This only works if the database supports this behavior and if generatedId() is also true for the field.
So if you have acc.id set to a non-0 value, it should be inserted into the database with the id from acc. If you want acc to get an auto-generated id then you should just set acc.id to be 0.
For an example, you could take a look at the ORMLite Android test class. Search for the testCreateWithAllowGeneratedIdInsert() method which has code like:
AllowGeneratedIdInsert foo = new AllowGeneratedIdInsert();
assertEquals(1, dao.create(foo));
AllowGeneratedIdInsert result = dao.queryForId(foo.id);
assertEquals(foo.id, result.id);
...
AllowGeneratedIdInsert foo3 = new AllowGeneratedIdInsert();
foo3.id = 10002;
assertEquals(1, dao.create(foo3));
result = dao.queryForId(foo3.id);
assertEquals(foo3.id, result.id);
NOTE: the docs mention that this only works if the database supports it but Sqlite is one of those databases.
Use Wrapper class instead of int
#DatabaseField(id = true)
private Integer id;

Android OrmLite emptyString for String defaultValue

I am using OrmLite 4.46 to manage my database for my android application.
And i have one problem:
I have the following code for my model:
public class Item extends Model {
#DatabaseField(generatedId = true)
private long id;
#DatabaseField(columnName = "item_name", defaultValue = "")
private String name;
#DatabaseField(columnName = "item_count", defaultValue = "0")
private int count;
public Item() {
super();
}
}
And the problem is here :
#DatabaseField(columnName = "item_name", defaultValue = "")
private String name;
When i am creating a new Item() with no arguments and i save it in the database, normally in the column item_name it should save an empty String.
But when i am retrieving the item from the database and i try
String itemName = item.getName().trim() I get a NullPointerException
So it seems that the name is null.
Also i checked the created table from the above model in the sqlite db file and when i set defaultValue="" the column is created with no default value.
Does anybody know of any solution to this problem?
You can initialize name field to empty string at class level like:
#DatabaseField(columnName = "item_name", defaultValue = "")
private String name = "";
This will initialize name field to empty string when you create object of class Item and save it to database.
When you retrieve it from database the name field will be empty ("") instead of null.
When i am creating a new Item() with no arguments and i save it in the database, normally in the column item_name it should save an empty String.
Although #Rakesh's answer is correct, this turns out to be a bug in ORMLite. The code is supposed to insert the defaultValue during a create if the field is null. However, there was an errant .equals("") that was stopping this.
I've submitted the following bug report and have fixed it in trunk. It will be in 4.47.

Categories

Resources