hope you have a good day.
I am new to greenDAO, and am wondering how to model a one-to-many relationship using greenDAO in an Android app so that I can retrieve a list of TestResult entities that belong to a User entity. I've used the #ToMany annotation at the User entity class and #ToOne at TestResult, following this documentation. However, even after persisting TestResult entity objects with the User property set, retrieving the same User causes a null error for its list of TestResult entity objects.
I would be greatly appreciate it if you guys would be so gracious as to to provide some help.
Thank you.
#Entity
public class Customer {
#Id private Long id;
#ToMany(referencedJoinProperty = "customerId")
#OrderBy("date ASC")
private List<Order> orders;
}
#Entity
public class Order {
#Id private Long id;
private Date date;
private long customerId;
}
Customer and Order are two entities. One customer have multiple orders. For this customerId is in order entity.
private long customerId;
In customer Entity,
#ToMany(referencedJoinProperty = "customerId")
#OrderBy("date ASC")
private List<Order> orders;
Reference
for details
Related
Please bear with me, i'm new to architecture components and android in general.
My question is similar to this question but unfortunately the accepted answer doesn't seem to work.
I have an example one to many relation like in this answer. My example database has two tables USERS and PETS as shown in the following images:
Let's say I want to get a list of users containing a list of their pets grouped by user id only with pets younger than 5.
The result should look like this (pseudo code):
{uId: 2, [Pet3, Pet4]; uId: 4, [Pet6, Pet7];}
Another requirement is that the Dao needs to return the list as a LiveData object because I'm using MVVM architecture and want it to be Lifecycle aware and observable.
With these requirements, the UserDao would look like this:
#Dao
interface UserDao {
#Insert
void insert(User user);
#Transaction
#Query("SELECT USERS.uId, PETS.pId , PETS.userId, PETS.age " +
"FROM USERS INNER JOIN PETS ON PETS.userId = USERS.uId " +
"WHERE PETS.age < 5 " +
"GROUP BY USERS.uId")
LiveData<List<UserWithPets>> getUserPets();
}
User Entity:
#Entity
public class User {
#PrimaryKey
public int id; // User id
}
Pet Entity:
#Entity
public class Pet {
#PrimaryKey
public int id; // Pet id
public int userId; // User id
public int age;
}
The problem is now: how should i design the UserWithPets that room understands it and maps the cursor the way i want?
Here is what i tried so far:
Approach 1:
The most convenient way in my opinion would be using a Relation, like in the POJO below.
UserWithPets POJO:
public class UserWithPets {
#Embedded
public User user;
#Relation(parentColumn = "id", entityColumn = "userId", entity = Pet.class)
public List<Pet> pets;
}
Unfortunately, the functionality to assign a condition to a relation is not yet implemented by google. So we always get a full list of pets for every user that owns a pet younger than 5. Hopefully this will be possible soon, since the feature request is already assigned here and here.
Statement from google from this feature request: "we are planning to implement some query rewriting logic to fix these, not for 2.1 but hopefully in 2.2 where we'll focus more on relations."
Approach 2:
Another option would be Embedding both, User and Pet like:
public class UserWithPets {
#Embedded
public User user;
#Embedded
public Pet pet;
}
This doesn't work either, because now we only get 1 pet per user.
Approach 3:
this answer suggests to just create a merged class that extends from user like:
public class UserWithPets extends User {
#Embedded(prefix = "PETS_")
List<Pet> pets = new ArrayList<>();
}
I tried in many ways, with contructor and without, but i can't get it to work. it always gives errors like "Entities and Pojos must have a usable public constructor. You can have an empty constructor or a constructor whose parameters match the fields (by name and type). - java.util.List"
or
The query returns some columns ... which are not used by UserWithPets. So any advice is welcome here.
Approach 4:
Just make two queries and stitch the results together. How would i do that using LiveData? Where should the joining operation be done? I can't do it in the Activity, that's not the point of an MVVM pattern. And not in the repository or viewmodel, since LiveData is immutable. Or is there another way?
What would be a working solution to get a result with the above requirements?
I have a list view in android where i have to check every time do display the List item or not
to reduce the requests what i did is saved the id in a single row like
1,2,10,
everything was working fine to search i just had to use
String[] favs = fav.split(",");
for (int index = 0; index <(favs.length); index++) {
if(favs[index]==""){}else {
wishlist.add(Integer.parseInt(favs[index].trim()));
}
if(clicklist.contains((int)temp.getId())) //like this
and to remove from db like, this
temp2.replaceAll(""+m1.getId()+",", "") // and save in the db
now issue is i have two more data field associated with id like
10|data1|data2,100|apple|dog,150|data12|data24
Question 1 is this data model ok for small db
Question 2 how to perform search and delete in new data set?
please help!
Using a db is a proper choice here, i suggest you to take a look to the recently released Room, an Android component made by Google developers to support data persistence more easily.
You should of course know the basis of sql language.
In your case you should annotate your data class with #Entity annotation:
#Entity
public class DataModel {
#PrimaryKey
private int uid;
#ColumnInfo(name = "animal")
private String animal;
#ColumnInfo(name = "fruit")
private String fruit;
// Getters and setters are ignored for brevity,
// but they're required for Room to work.
}
And then, to answer your question about CRUD operations, define a Dao:
#Dao
public interface UserDao {
#Query("SELECT * FROM DataModel")
List<DataModel> getAll();
#Insert
void insertAll(DataModel... dataModels);
#Delete
void delete(DataModel dataModel);
}
I am using greenDao in my app to persist complex object.
For example
class A{
id;
name;
List<B> list;
}
class B{
id;
name;
List<C> list;
}
class c{
id;
name;
}
I got the tables with all class fields(for all classes).
Problem:
I can see records for table A(for class A), tables B and C are empty(no records).
I am persisting object of class A like:
A toSave = //class generated by GSON
aDao = daoService.getADao();
aDao.insert(toSave);
Can you please help me to solve this issue?
Also I cannot find in the documentation if is allowed to query dao object and retrieve object of class A with all information/fields automatically?
thanks!
I have found the solution:
GreenDao is not able to persist cascade data - If you say insertOrReplace(tvShow) it will not persist list of episodes and list of moments. In order to perform that you have to persist all data separately.
For example:
TvShowDao.save(tvShows) OR TvShowDao.insertOrUpdate(tvShows);
AND
EpisodesDao.save(episodes) OR EpisodesDao.save(episodes)
AND
MomentDao.save(moments); OR MomentDao.save(moments);
Important:
Note that save...() will do
an insert for entities that have no ID and
will do an update for entities that have an ID set.
GreenDao Git Issue
In other words, you have to persist all data separately.
I have the following 3 classes:
1) TvShow
#Entity
public class TvShow{
#Id
private String uuid;
private String url;
private String title;
...
#ToMany(referencedJoinProperty = "tvShowUuid")
private List<Episode> episodes;
2) Episode
#Entity
public class Episode{
#Id
private String uuid;
#ToMany(referencedJoinProperty = "episodeUuid")
private List<Moment> moments;
//FK
private String tvShowUuid;
3) Moment
#Entity
public class Moment{
#Id
private String uuid;
...
private String episodeUuid;
As you can see the relationship between them is: TvShow --> oneToMany --> Episode --> oneToMany --> Moment
Assuming I have a fully populated TvShow object (called tvShow), I am doing the following to add that object to my database:
final long rowId = daoSession.getTvShowDao().insertOrReplace(tvShow);
This correctly adds the tvShow object to the TvShow table. However, the Episode and Moment tables are NOT populated at all. The tvShow object has several Episodes and each episode has several moments. I was expecting the other 2 tables to contain that data as well, but they don't.
What am I doing wrong? Am I supposed to loop through each Episode (and in turn loop through each Moment of each episode) and insert them manually instead? =(
Maybe I will be wrong, I have had the same problem, but greenDao is not able to persist cascade data - If you say insertOrReplace(tvShow) it will not persist list of episodes and list of moments. In order to perform that you have to persist all data separately.
For example:
TvShowDao.save(tvShows) OR TvShowDao.insertOrUpdate(tvShows);
AND
EpisodesDao.save(episodes) OR EpisodesDao.save(episodes)
AND
MomentDao.save(moments); OR MomentDao.save(moments);
In other words, you have to persist all data separately.
I hope so that this helped you.
I have two tables (Dog & Person) defined in Realm object and need use 1:n relation.
My Person class is:
public class Person extends RealmObject {
#PrimaryKey
private int id;
private int age;
private Dog dog;
/** Getters & setters **/
}
My Dog class is:
public class Dog extends RealmObject {
#PrimaryKey
public int id;
public String name;
/** Getters & setters **/
}
When the table "Dogs" contains data loading from internet. I need add dog id to my Person table as relationship, when save object Person. If save to "Person" table dogId, than i dont join data. I need select data from Person include dog name.
Is possible in realm as relationship? Or I use another realm query, where i will search by dog where id?
Thank you for response.