I have the following structure to save to app database:
#Entity
public class Project{
#primaryKey
String id;
String name;
[...]
Country country;
[...]
}
And my Country Entity looks like the following:
#Entity
public class Country {
#PrimaryKey
private String id;
private String name;
private String pk;
}
Now to my Question: How do I make Room know the Relation between Country and Project Entity?
Room can not have nested entities, you can embedd POJO classes in an entity but it will get flattened into a single table or if you want Country as an entity then you'll have to store county_id in Project entity and index it as foreign key.
More on Embedded fields: https://developer.android.com/reference/android/arch/persistence/room/Embedded.html
More on Foreign key: https://developer.android.com/reference/android/arch/persistence/room/ForeignKey.html
Please refer the official documentation
https://developer.android.com/reference/android/arch/persistence/room/Relation.html
Related
I'm having trouble understanding how to set up my Room relationships. I haven't found an example analogous to mine anywhere online.
I have a User object (I've left out getters and setters):
#Entity
public class User {
#PrimaryKey
#NonNull
private String userId;
#ColumnInfo
private String name;
#ColumnInfo
private List<Long> seminarsAttended;
}
and a Seminar object:
#Entity
public class Seminar {
#PrimaryKey
private Long seminarId;
#ColumnInfo
private String topic;
....}
The list "seminarsAttended" in the User object is a list of seminarIds. The User class is linked up to a Retrofit call, so I can't modify the class to instead hold a list of Seminar objects.
How can I model this relationship in Room, such that the seminarIds in the User's seminarsAttended list are correlated with their corresponding Seminar in the seminars.db table?
It looks like the list of seminarsAttended should be a list of foreign keys into the seminars.db table, but I'm having trouble finding an example.
I've been using SugarDB for most of my projects in the past. It was easy to use and satisfied most of my requirements but since that project has been abandoned, decided to look at alternatives and Room seems like the best option.
However, some basic things are quite confusing in Room. My Object uses Gson to populate data from a webservice, and as such as links to other objects. As an example, consider the classes below:
#Entity
public class TestModel
{
#PrimaryKey(autoGenerate = true)
private int id;
private String name;
private String age;
private List<Book> issuedBooks;
}
public class Book
{
private String title;
private int ISBN;
}
Now if my first class is annotated as the Entity, will this automatically treat classes referenced inside it as entities as well?
If I save an object of TestModel, will it save the list of Books with it to the database?
I guess you can do it this way.
#Entity
public class TestModel {
#PrimaryKey
public int id; // TestModel id
public String name;
public String age;
}
#Entity
public class Book {
#PrimaryKey
public int id; // Book id
public int testModelId; // TestModel id
public String title;
public int ISBN;
}
public class TestModelWithBooks {
#Embedded
public TestModel testModel;
#Relation(parentColumn = "id", entityColumn = "testModelId", entity = Book.class)
public List<Book> books;
}
For their Dao, you can write it this way.
#Dao
public interface TestModelDao {
#Query("SELECT * FROM TestModel")
public List<TestModelWithBooks> loadTestModelsWithBooks();
}
will this automatically treat classes referenced inside it as entities as well?
No. In fact, I would expect your code to fail to compile. You would need to:
Make Book be an #Entity
Remove issuedBooks from TestModel
Set up a #ForeignKey relationship between Book and TestModel
If I save an object of TestModel, will it save the list of Books with it to the database?
No.
Room is not an ORM. Room is a thin object wrapper around SQLite. #Entity and #ForeignKey model the table structure. IMHO, the simplest way to think of Room as it being DTOs to the database. Your model objects that represent your object graph are not the entities, but instead are built from the entities. This is akin to how responses from a Web service (e.g., Retrofit) are DTOs to the server, and you may need to map from those objects to the "real" model objects that you want to use in the app.
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.
There is User table in APP version 1.0:
#Table(name="User1")
public class User extends RealmObject {
#PrimaryKey
public int uid;
#Required
public String name;
}
In APP version 2.0, add a field age:
#Table(name="User2")
public class User extends RealmObject {
#PrimaryKey
public int uid;
#Required
public String name;
public int age;
}
I usually change User table name in version 2.0 by changing annotation, because it's easier then call ADD COLUM age.
How should i do in realm API?
i've try #DefineTable but does not work.
#RealmClass(name = "reviewWords")
open class ReviewWords : RealmObject() {}
The 'table' name of the model in Realm's underlying storage engine is decided by the class name. Realm doesn't have either #Table or #DefineTable annotation to name the 'table' right now.
If you want to change it, you can just rename the class and implement the proper migration. See https://realm.io/docs/java/latest/#migrations.
I'm trying to map my classes to the SQLite database using ORMLite and i have trouble to store a collection of String i have this error :
java.lang.IllegalArgumentException: No fields have a DatabaseField annotation in
class java.lang.String
this error is self explanatory but how i do to store a collection of strings should i extend String class and add the annotations needed in order to do that ?
in the annotation of the field i added datatype.serializable but that too wouldn't work.
here's my class where i have the problem :
#DatabaseTable(tableName = "parameters")
public class Parameters {
// id is generated by the database and set on the object automagically
#DatabaseField(generatedId = true)
int id_parameters;
#DatabaseField(canBeNull = true)
#JsonProperty("id")
private Integer id;
#DatabaseField(canBeNull = false)
#JsonProperty("account_id")
private Integer account_id;
#ForeignCollectionField
#JsonProperty("languages")
private Collection<String> languages;
...
}
the field in question is languages!
Yeah, you can't just do a collection of strings. You will need to create a wrapper class with a String field in it as well as a foreign Parameters field:
public class Language {
#DatabaseField(generatedId = true)
int id;
#DatabaseField
String language;
#DatabaseField(foreign = true)
Parameters parameters;
}
Here's the description of foreign collections from the FM. To quote:
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.