ActiveAndroid Nested Model - android

I am using ActiveAndroid and have two models:
#Table(name = "Topics")
public class Topic extends Model {
#Column(name = "Name") String name;
#SerializedName("id")
#Column(index = true,
unique = true,
onUniqueConflict = Column.ConflictAction.REPLACE) public long topic_id;
#Column(name = "Counts",
onUpdate = Column.ForeignKeyAction.CASCADE,
onDelete = Column.ForeignKeyAction.CASCADE) Counts counts;
}
and
#Table(name = "Counts")
public class Counts extends Model {
#Column(name = "Users") int users;
}
Constructors have been excluded for brevity.
Now, when i save Topic, I expect the Counts to be saved. But it does not.
I am using gson to create the models from json. Any reason why counts are not being loaded?

First you have to call count.save() then you can call topic.save(). ActiveAndroid needs the id to get the reference and that happen when you save it.

Related

How to link Room database entities on android?

I am quite familiar with these kind of thing on Spring JPA but I can not make it work on Android. I post my code below so you can understand the question better. I have two classes and a third class that needs to contain objects of class 1 and 2. I know that the code for the third class is not correct, since Room does not support object references like that. If I save just the id-s of the objects as foreign keys I am not able to query after the results.
There must be some kind of nice solution for this problem. Thank you.
#Entity(tableName = "soup")
public class Soup {
#PrimaryKey(autoGenerate = true)
private long id;
private String name;
// getter and setters
}
#Entity(tableName = "main_course")
public class MainCourse {
#PrimaryKey(autoGenerate = true)
private long id;
private String name;
// getter and setters
}
#Entity(tableName = "menu")
public class Menu {
#PrimaryKey(autoGenerate = true)
private long id;
private Soup soupOptionOne;
private Soup soupOptionTwo;
private Soup soupOptionThree;
private MainCourse courseOptionOne;
private MainCourse courseOptionTwo;
private MainCourse courseOptionThree;
}

How to handle relationships in Room?

I'm testing Room persistence library. I have two entity classes:
#Entity
public class User {
#PrimaryKey
int id;
String name;
}
#Entity(foreignKeys = #ForeignKey(entity = User.class,
parentColumns = "id",
childColumns = "userId")
public class Pet {
#PrimaryKey
int id;
String name;
int userId;
}
Now I'd like to get list of Pet and in each Pet object keep actual reference to User according to his userId. So each time when the userId is changed, this reference also should be changed. Is it possible to do? Or maybe there is a better way to handle relation like this?
Actually, ROOM not recommended to do that. The reasons are in the reference link.
Maybe you could try it,
#Entity
public class User {
#PrimaryKey
int id;
String name;
#Embedded
public List<Pet> userPet;
}
public class Pet {
int id;
String name;
}
Understand why Room doesn't allow object references
A convenience annotation which can be used in a Pojo to automatically fetch relation entities.

Class with collection of itself ORMLite

How can i create one-to-many relation with the table itself in ormlite? I have a class that holds collection of itself. I don't know how to map this class.
#DatabaseTable(tableName = "USER")
public class User {
#DatabaseField(generatedId = true)
private long id;
#DatabaseField
private String username;
#ForeignCollectionField
private ForeignCollection<User> friends;
...
Thanks in advance.
I have a class that holds collection of itself. I don't know how to map this class.
I think the best way would be to define a UserFriend entity that has a reference to the owner User, friend User, and an id. Something like:
#DatabaseTable(tableName = "USERFRIEND")
public class UserFriend {
#DatabaseField(generatedId = true)
private long id;
// corresponds to the user who has the friend
#DatabaseField(foreign = true)
private User user;
// corresponds to the friend of the user
#DatabaseField(foreign = true)
private User friend;
...
Then your foreign collection becomes:
#ForeignCollectionField(foreignFieldName = 'user')
private ForeignCollection<UserFriend> friends;
Notice the foreignFieldName which has to point to the user so the user's friends can be found.

List<String> as a #ForeignCollectionField ormlite

I have in my model Class
List<String> _photo_array;
since I can put anotation on String Class is it a way to persist it using ormLite?
since I can put anotation on String Class is it a way to persist it using ormLite?
You are going to have to create an entity that wraps the String. Something like:
#DatabaseTable
public class Photo {
#DatabaseField(generatedId = true)
private int id;
#DatabaseField
private String photo;
#DatabaseField(foreign = true)
private Model model;
}
Then your model class would have a ForeignCollection of these photos.
#DatabaseTable
public class Model {
#DatabaseField(generatedId = true)
private int id;
#ForeignCollectionField()
private ForeignCollection<Photo> photos;
}
See the foreign collection example.
One way to solve this problem is to use one-to-many relations.
To persist one-to-many relations you can should use ForeignCollection.
Check the docu.
Other types of collections are not supported by ORMLite, as I know.
Another point is you need a back-reference in the referenced Object.
To mark a field as back-reference, use annotation #DatabaseField(foreign = true, ... )
For Scenario A(1) -> B(n)
class A {
#DatabaseField(generatedId = true, columnName = BaseColumns._ID)
public int _id;
#ForeignCollectionField(eager = true)
public ForeignCollection<B> _photo_array;
}
class B {
#DatabaseField(generatedId = true, columnName = BaseColumns._ID)
public int _id;
#DatabaseField(foreign = true, canBeNull = false,
foreignAutoRefresh = true, foreignAutoCreate = true)
public A a;
}
In this scenario A reference B in one-to-many way. If a will be loaded, all dependent B's will also be loaded (because of eager = true)
To save this structure you could use this way (i hope you have allready created ADao and BDao classes):
final A a = ...;
final ADao aDAO = ...;
aDAO.createOrUpdate(a);
final ArrayList<B> children = ...;
final BDao bDAO = ...;
for (final B b: children ) {
bDAO.create(season);
}
A and B including dependency will be stored. If you now try to get A from db you will also get all B's related to instance of A.

Caching nested objects in Robospice with ORMLite

Is it possible to cache nested (2-3 level of nesting) objects (foreign fields) via Robospice/ORMlite?
https://groups.google.com/forum/#!msg/robospice/VGLB3-vM3Ug/-piOac212HYJ - there you can read that is possible, but unfortunatelly I can't achieve it.
Here is my source code:
#DatabaseTable(tableName = "city")
#JsonIgnoreProperties(ignoreUnknown = true)
public class City {
#DatabaseField(id = true)
#JsonProperty("id")
private long id;
#DatabaseField
#JsonProperty("name")
private String name;
#ForeignCollectionField(eager = true, maxEagerLevel = 3)
#JsonProperty("clubs")
private Collection<Club> clubs;
...
#DatabaseTable(tableName = "club")
#JsonIgnoreProperties(ignoreUnknown = true)
public class Club {
#DatabaseField(id = true)
#JsonProperty("user_id")
private long id;
#DatabaseField
#JsonProperty("name")
private String name;
#DatabaseField(foreign = true, foreignAutoRefresh = true, columnName = "city_id", maxForeignAutoRefreshLevel = 2)
private City city;
#DatabaseField(foreign = true)
#JsonProperty("address")
private VenueAddress address;
...
#DatabaseTable(tableName = "address")
#JsonIgnoreProperties(ignoreUnknown = true)
public class VenueAddress {
#DatabaseField(id = true)
#JsonProperty("uid")
private long id;
#DatabaseField
#JsonProperty("street")
private String street;
#DatabaseField
#JsonProperty("street_number")
private String streetNumber;
#DatabaseField
#JsonProperty("country")
private String country;
#DatabaseField(foreign = true, foreignAutoRefresh = true, columnName = "club_id", maxForeignAutoRefreshLevel = 2)
private Club club;
...
And sample SpiceService:
public class SampleSpiceService extends SpringAndroidSpiceService {
private static final int WEBSERVICES_TIMEOUT = 10000;
#Override
public CacheManager createCacheManager(Application application) {
CacheManager cacheManager = new CacheManager();
List<Class<?>> classCollection = new ArrayList<Class<?>>();
// add persisted classes to class collection
classCollection.add(VenueAddress.class);
classCollection.add(City.class);
classCollection.add(Club.class);
// init
RoboSpiceDatabaseHelper databaseHelper = new RoboSpiceDatabaseHelper(application,
"sample_database.db", 5);
InDatabaseObjectPersisterFactory inDatabaseObjectPersisterFactory = new InDatabaseObjectPersisterFactory(
application, databaseHelper, classCollection);
cacheManager.addPersister(inDatabaseObjectPersisterFactory);
return cacheManager;
}
#Override
public RestTemplate createRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
// set timeout for requests
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setReadTimeout(WEBSERVICES_TIMEOUT);
httpRequestFactory.setConnectTimeout(WEBSERVICES_TIMEOUT);
restTemplate.setRequestFactory(httpRequestFactory);
MappingJacksonHttpMessageConverter messageConverter = new MappingJacksonHttpMessageConverter();
restTemplate.getMessageConverters().add(messageConverter);
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
return restTemplate;
}
}
And when I fetch City object from cache it has clubs collection, but VenueAddress in each Club has null fields (except id).
Do you have any advices?
This is more a ORM Lite question than a RoboSpice thing.
Maybe you could "embed" the address data inside the club entitiy/table.
This thread might be of interest :
one-to-one relationship in Ormlite
The problem may come from here as stated in ormlite docs :
foreignAutoRefresh
Set this to be true (default false) to have a foreign field automagically refreshed when an object is queried. The default is to just have the ID field in the object retrieved and for the caller to call refresh on the correct DAO. If this is set to true then, when the object is queried, a separate database call will be made to load of the fields of the foreign object via an internal DAO. NOTE: this will not automagically create the foreign object if you create an object that has this field set.
NOTE: This will create another DAO object internally so low memory devices may want to call refresh by hand.
NOTE: To protect against recursion, there are a couple of places were auto-refreshing has been limited. If you are auto-refreshing a class that itself has field with foreignAutoRefresh set to true or if you are auto-refreshing a class with a foreign collection, in both cases the resulting field will be set to null and not auto-refreshed. You can always call refresh on the field directly if you need it.

Categories

Resources