Curtently, my app loads some data from rest webservice, using spring's RestTemplate and java pojo classes with Jackson.
So as a result, I have java objects, containing data retrieved from webservice.
But I also need to have my data available for offline use. So my idea is to save data to sqlite database. Can I use my pojo classes as a models for ormlite to save/load data?
I want to directly save my data to sqlite, using pojo class objects that I already have as ormlite models, is it possible with ormlite? Note that my pojo classes contain fields declared as other pojo object, so probably there will be needed some table structure with foreign keys. Can it be handled automatically by ormlite?
You have to annotate your POJO Model with proper ormlite annotations #DatabaseTable and #DatabaseColumn.
Nextly you have to build up a class(eg. OrmDatabaseHelper) that extends OrmLiteSqliteOpenHelper;
Afterwards you can inject object like this
#OrmLiteDao(helper = OrmDatabaseHelper.class)
Dao<YourCustomPOJO, Long> yourCustomDao;
Long stands for the ID field type.
This allows you to use dao's methods like create, delete, queryForAll etc.
YourCustomPOJO pojo = new YourCustomPOJO();
//set some values
yourCustomDao.create(pojo);
Related
Having Room used in Android app, I created entity objects as required. Also, having decoupled layered architecture, I use Room entities only in data layer, converting them further to domain objects to be used in use case and UI layers.
Now, the problem is following:
Room provides us with very convinient way to to CRUD operations with simple anotating methods and providing Entity object.
But, how can we achieve that when Entities (and DB tables) have some meta data fields that are used only in db layer, and I don't map them to domain objects.
Here is an example of two simple classes from different layers (without annotations, for convenience):
data class CarDbEntity(id: Int, brand: String, color: String, _createdAt: Long, _someOtherMeta: Int)
data class CarDomainObject(id: Int, brand: String, color: String)
Now, I have convertors from DbEntity to DomainObject classes. But it cannot be done vice versa, since I am not mapping _metaFields to DomainObjects. Which means, since I cannot properly recreate DbEntity class, I cannot use convinient ways of crudding like this:
#Update
fun updateCar(car: CarDbEntity)
So, if I want to update car brand name or color, I need to write manually custom #Query with SQL for each case I need it.
I even tried creating CarWithNoMetaDbEntity trying to attach it to the same table as CarDbEntity, hoping that it would update just fields that exist in that class (and leave _meta as it is) but Room doesn't allow multiple entity classes bound to the same table.
Is there any technique where I can achieve updating such objects easily, without writing bunch of update SQL queries?
Are those two interchangable in context of Room database entity, or, if not, what are the differences between them?
#Ignore is a Room-specific annotation, saying that Room should ignore that field or method.
transient is a Java construct, indicating that this field should not be serialized in standard Java serialization. Room happens to treat this similarly to #Ignore by default. Mostly, that is there for cases where you are inheriting from some class that happens to use transient and you do not control that class (e.g., it is from a library).
For your own code, if you are not using Java serialization, I recommend sticking with #Ignore for the fields. transient is not an available keyword for a method, so to tell Room to ignore certain constructors, you have no choice but to use #Ignore.
Adding to CommonsWare's answer
transient is not good option for ignoring fields for Room as CommonsWare answered. It will create blocker when same modal is being used to parse data from server and store into database.
Let's assume you have a modal class MyModal.java as below
public static class MyModal {
#SerializedName(“intField”)
public int intField;
#SerializedName(“strField”)
public String strField;
#SerializedName(“booleanField”)
public boolean booleanField;
}
If you want to NOT SAVE booleanField into database, and if you modified that field as
transient : It will ignore this field while saving into database, BUT it will also ignore this field while parsing data which comes from server.
#Ignore : It will only ignore this field while inserting data into database, but this field will participate into json parsing.
I started using realm. it seemed to work fine, but I have some questions. When I use realm for simple object with primitive fields, everything is ok. But I'm facing issues using it for complex objects.
For example I have a class Passenger. It has several fields
Segment segment;
Documents documents;
....
Each field also has sub objects. Segment class
Flight flight;
Arrival arrival;
int pnrRequest;
So as I understand I will have several tables and I need one-to-many relations to connect this tables. What i want is to store passenger list inside database.
The problem is that I already have this classes as a model, but they dont extend RealmObject. I don't want to have duplicate classes one for model and one for database. Is there a way to avoid duplication of files and conversion from one model to another?
According to documentation it's posible:
An alternative to extending the RealmObject base class is implementing the RealmModel interface and adding the #RealmClass annotation.
Realm requires that all models that should be persisted must extend RealmObject or implement the interface RealmModel (see https://realm.io/docs/java/latest/#realmmodel-interface). If neither of these approaches work for you, you will need to duplicate the class and have conversion methods between them.
I have my app's networking code separated into a separate package. This package contains a POJO model that I'm serializing with Gson (using its #Expose annotation):
public class User {
#Expose
String username;
#Expose
String pathToAvatar;
// etc.
}
My app also is using ActiveAndroid as a database wrapper. I would like to extend the .networking.User model and add a couple more database-specific fields (secretKey or something) in my main logic. It would be nice if the networking code did not know its model was being used in a database. Unfortunately, I'm having to have .networking.User extend the ActiveAndroid Model base class (and having to label each networking variable with #Column). This works, with one problem: I'm getting a dummy User database table that corresponds with the networking code's class, even though it is not annotated with #Table, simply because it derives from Model. The main code's table is created correctly.
Can I prevent ActiveAndroid from creating a table when it finds a certain Model? Alternatively, is there a better way to approach this?
I am trying to maintain a local store of a database, accessible via a REST API. I am attempting to use the fantastic RoboSpice and Spring libraries for the REST client, Jackson to parse/cache the JSON response and ORMLite to persist the resulting objects.
The problem is that I don't know how to store foreign object relationships for the JSON responses I get. Sometimes the JSON objects are nested, other times they are referenced by Id.
A typical systems response
{
id:567,
name:"The only system",
competitions:[{
id:123,
system_id:567
...
}];
}
A competitions response
items: {
123:{
id:123,
system_id:567 // System only referenced by id
...
}}
Another competitions response
items: {
123:{
id:123,
system_id:567, // System referenced by id and nested
system:{
id:567,
name:"The only system",
...
}
}
}
Nested objects work fine, but it's the cases where there is a reference by id that is killing it. I have two classes for my data model as follows.
Systems class
#DatabaseTable("systems")
public class System {
#JsonProperty("id")
#DatabaseField(id=true, columnName="id")
private long id;
#JsonProperty("name")
#DatabaseField(columnName="name")
private String name;
#JsonProperty("competitions")
#ForeignCollectionField
private ForeignCollection<Competition> competitions;
// getters & setters omitted
}
Competition class
#DatabaseTable("competitions")
public class Competition {
#JsonProperty("id")
#DatabaseField(id=true,columnName="id")
private long id;
#JsonProperty("system_id")
#DatabaseField(columnName="id")
private long systemId; // This is definitely at least part of the problem
#JsonProperty("system")
#DatabaseField(foreign=true, columnName="system_id")
private System system;
// getters & setters omitted
}
Having two properties references the system_id seems like a definitively bad idea, but I can't find an alternative for the behaviour I want. Even if the system object is not nested in the Competition object, the Competition should be able to map a relationship to the System object in the local database, because the id of the system is always provided.
The other problem I suspect is that I'm using two object persisters, the JacksonObjectPersister and the InDatabaseObjectPersisterFactory (provided by RoboSpice for use with ORMLite). The reason for this is because I don't want to persist the lists that the objects are nested in to the database. By my understanding, Jackson should cache the JSON response from the server, ORMLite should cache the data model.
This is the error I'm getting
02-03 15:15:57.640: D//DefaultRequestRunner.java:166(20944): 15:15:57.636 Thread-28
An exception occurred during service execution :org.codehaus.jackson.map.JsonMappingException:(was java.lang.NullPointerException)
(through reference chain: com.company.app.api.objects.List["items"]->
java.util.HashMap["51"]->
com.company.app.api.objects.Competition["system_id"])
Apologies for what seems like a number of questions in one, I am bashing my head against a wall. I will attempt to wrap this essay up with a summary...
Is there any way to piece together object relationships using Jackson and ORMLite for the JSON responses I have provided?