Green DAO relationship - android

This is my code :
Schema schema = new Schema(1, "com.core.greendao.db");
/* Topic Model Table */
Entity topic = schema.addEntity("Topic");
topic.addLongProperty("topic_id").primaryKey();
topic.addStringProperty("group_id").notNull();
topic.addStringProperty("user_id");
topic.addStringProperty("slug");
topic.addStringProperty("message");
topic.addStringProperty("reply_count");
topic.addStringProperty("like_count");
topic.addStringProperty("anon_status");
topic.addStringProperty("link_data");
topic.addStringProperty("created_at");
topic.addStringProperty("locale");
topic.addIntProperty("status");
/* Reply Model Table */
//TODO: Topic id add for relation
Entity reply = schema.addEntity("Replies");
reply.addLongProperty("reply_id").primaryKey();
reply.addStringProperty("message");
reply.addStringProperty("reply_count");
reply.addStringProperty("like_count");
reply.addStringProperty("anon_status");
reply.addStringProperty("link_data");
reply.addStringProperty("created_at");
reply.addStringProperty("locale");
reply.addIntProperty("status");
/* User Model Table */
//TODO: Topic id to add for relation
Entity user = schema.addEntity("User");
user.addIdProperty();
user.addLongProperty("user_id");
user.addStringProperty("url");
user.addStringProperty("fullname");
user.addStringProperty("tagline");
user.addStringProperty("image");
user.addStringProperty("category_title");
/* Actions */
//TODO: Topic id and Reply id for relation
Entity actions = schema.addEntity("Actions");
actions.addIdProperty();
actions.addLongProperty("user_id");
actions.addStringProperty("url");
/*******************************************************************/
Property topicIdForTopicUser = user.addLongProperty("topic_id").notNull().getProperty();
user.addToOne(topic, topicIdForTopicUser);
Property topicIdForTopicAction = actions.addLongProperty("topic_id").notNull().getProperty();
actions.addToOne(topic, topicIdForTopicAction);
Property topicIdForReply = reply.addLongProperty("topic_id").notNull().getProperty();
reply.addToOne(topic, topicIdForReply);
/*******************************************************************/
As per the structure, topic_id is a primary key in the Topic table and is foreign key in the User, Action, and Replies tables.
I am getting proper values from the Topic table. But getting null point when I try to get values from other table on the basis of topic_id.
Any help appreciated.

You need to use .addToOne(table, property) method to specify the relationship. You also don't need to specify the id for the object, you can just use .addIdProperty() For example
Schema schema = new Schema(1, "com.core.greendao.db");
Entity user = schema.addEntity("User");
user.addIdProperty();
Entity topic = schema.addEntity("Topic");
topic.addIdProperty();
Property userId = topic.addLongProperty("user_id").notNull().getProperty()
topic.addToOne(user, userId);
See GreenDAO docs for more examples of relationships.

Related

How to use parameter fields in Room #Query?

I have a User class with a field id, so I wanted to run the following query with Room:
#Query("SELECT * FROM ticket where user_id = :user.id")
LiveData<Ticket> loadFromUser(User user);
But I am getting error marks on Android Studio on user.id and all examples I find online only use the direct parameter of the #Query method, usually a String or an int.
Is it possible to use an object's field in a Room #Query? If positive, so what's the proper way of referencing it.
You can't pass parameters like that to room. It does not support a full expression language. You have to use primitive types to pass parameters. Like this,
#Query("SELECT * FROM ticket where user_id = :user_id")
LiveData<Ticket> loadFromUser(String user_id);
A simple solution is to create two other functions, one is for user_id and one is for user as follows:
#Query("SELECT * FROM ticket where user_id = :user_id")
LiveData<Ticket> loadFromUser(String user_id);
#Transaction
LiveData<Ticket> loadFromUser(User user){
return loadFromUser(user.id);
}
in my case i used #RawQuery
in DAO you can write
#RawQuery
LiveData<Ticket> loadFromUser(SupportSQLiteQuery query);
and create your query and pass to it.
SimpleSQLiteQuery query = new SimpleSQLiteQuery("SELECT * FROM ticket where user_id = ?") , new Object[]{user.id})
and pass this query to DAO method.
userDao.loadFromUser(query)

How to implement relationships in Greendao?

I am new to Greendao.I am writing a generator for generating entities in greendao.So,I have two entities Hospital and patient. They have a one to many relationship between them. So,a hospital can have many patients but one patient can have only one hospital. Now Property hospitalId = patient.addLongProperty("hospitalId").getProperty(); this adds a hospitalid column to patient table. and
ToMany hospitalToPatients = hospital.addToMany(patient, hospitalId);
This line creates a one to many relationship between hospital and patient.So what is the use of the lines patient.addToOne(hospital, hospitalId); and hospitalToPatients.setName("patients"); How to implement one to one,one to many,many to one and many to many relationships in greendao ?
PS: I copied this code from http://www.vertabelo.com/blog/technical-articles/a-comparison-of-android-orms
public class ProjectGenerator {
public static void main(String[] args) throws Exception {
Schema schema = new Schema(1, "com.example.project");
// hospital table
Entity hospital = schema.addEntity("Hospital");
hospital.addIdProperty();
hospital.addStringProperty("name");
// patient table
Entity patient = schema.addEntity("Patient");
patient.addIdProperty();
patient.addStringProperty("name");
Property hospitalId = patient.addLongProperty("hospitalId").getProperty();
// patient has a one assigned hospital
patient.addToOne(hospital, hospitalId);
// hospital has many patients
ToMany hospitalToPatients = hospital.addToMany(patient, hospitalId);
hospitalToPatients.setName("patients");
// trigger generation with path to the Android project
new DaoGenerator().generateAll(schema, "../project/src/main/java");
}
}
So what is the use of the lines patient.addToOne(hospital, hospitalId)
This line is creating a oneToOne relation between hospital and patient .
hospitalToPatients.setName("patients")
This is just setting the name of foreign key .
As you can see, you have already implemented implement one to one,one to many relationship in your example . patient.addToOne is an example of OneToOne relationships . hospital.addToMany is an example of OneToMany relationships . And greenDao doesn't support ManyToMany relationship directly for more details you can read this .

Inserting to a to-many relation

If i have for example a table Shows and i have a to-many relation to a table Actors
When inserting a Show which doesn't have id(its auto-generated), how can i insert Actors if i don't have id of the show to relate to?
Here is DaoGenerator code:
Entity show = schema.addEntity("Show");
show.setHasKeepSections(true);
show.addIdProperty();
show.addIntProperty("tvdb_id").notNull();
show.addStringProperty("title");
show.addIntProperty("year");
show.addStringProperty("url");
show.addLongProperty("first_aired");
show.addStringProperty("country");
show.addStringProperty("overview");
show.addIntProperty("runtime");
show.addStringProperty("status");
show.addStringProperty("network");
show.addStringProperty("air_day");
show.addStringProperty("air_time");
show.addStringProperty("certification");
show.addStringProperty("imdb_id");
show.addIntProperty("tvrage_id");
show.addLongProperty("last_updated");
show.addIntProperty("rating");
show.addIntProperty("votes");
show.addIntProperty("loved");
show.addIntProperty("hated");
Entity actor = schema.addEntity("Actor");
actor.addIdProperty();
actor.addStringProperty("name");
actor.addStringProperty("character");
actor.addStringProperty("image");
Property showId = actor.addLongProperty("show_id").notNull().getProperty();
ToMany showToActor= show.addToMany(actor, showId);
showToActor.setName("actors");
The ID is auto-generated when you insert the object.
So you have to insert the show before adding actors to it.
You can just call refresh() on that entity, the current copy would get updated and so its id.
Then you should take this showId and set it to each actor's show id.
show.refresh();
for (Actor actor : actors)
actor.setShowId(show.getId());
actorDao.insertAllInTx(actors);

How to save protocol buffer classes directly using GreenDao

GreenDao provides an addProtobufEntity method to let you persist protobuf objects directly. Unfortunately I can't find much documentation explaining how to use this feature.
Let's say I'm trying to add a foreign key into my Message entity so I can access its PBSender protobuf entity. Here's my generator code:
// Define the protobuf entity
Entity pbSender = schema.addProtobufEntity(PBSender.class.getSimpleName());
pbSender.addIdProperty().autoincrement();
// Set up a foreign key in the message entity to its pbSender
Property pbSenderFK = message.addLongProperty("pbSenderFK").getProperty();
message.addToOne(pbSender, pbSenderFK, "pbSender");
Unfortunately the generated code doesn't compile because it is trying to access a non-existant getId() method on my PBSender class:
public void setPbSender(PBSender pbSender) {
synchronized (this) {
this.pbSender = pbSender;
pbSenderID = pbSender == null ? null : pbSender.getId();
pbSender__resolvedKey = pbSenderID;
}
}
Can anybody explain how relationships to protocol buffer entities are supposed to be managed?
GreenDao currently only supports Long primary keys. Does my protobuf object need a method to return a unique Long ID for use as a primary key?
If I remove my autoincremented ID then the generation step fails with this error:
java.lang.RuntimeException: Currently only single FK columns are supported: ToOne 'pbSender' from Message to PBSender
The greenDAO generator Entity source code suggests it currently does not support relations to protocol buffer entities:
public ToMany addToMany(Property[] sourceProperties, Entity target, Property[] targetProperties) {
if (protobuf) {
throw new IllegalStateException("Protobuf entities do not support realtions, currently");
}
ToMany toMany = new ToMany(schema, this, sourceProperties, target, targetProperties);
toManyRelations.add(toMany);
target.incomingToManyRelations.add(toMany);
return toMany;
}
/**
* Adds a to-one relationship to the given target entity using the given given foreign key property (which belongs
* to this entity).
*/
public ToOne addToOne(Entity target, Property fkProperty) {
if (protobuf) {
throw new IllegalStateException("Protobuf entities do not support realtions, currently");
}
Property[] fkProperties = {fkProperty};
ToOne toOne = new ToOne(schema, this, target, fkProperties, true);
toOneRelations.add(toOne);
return toOne;
}
However, I suspect that you could make this work if your Protobuf class contains a unique long ID and a public Long getId() method to return that ID.

greendao Left join dilemma

I'm using greenDao and I need to extract data from several tables similar to left-join funcionality. Here's a cite from my schema generator:
private static void genRetailers(Schema schema) {
// create retailer entity
Entity retailerEntity = schema.addEntity("Retailer");
retailerEntity.addIdProperty().notNull();
retailerEntity.addStringProperty("title");
Entity shopEntity = schema.addEntity("Shop");
shopEntity.addIdProperty().notNull();
shopEntity.addStringProperty("address");
Property retailerId = shopEntity.addLongProperty("retailerId")
.getProperty();
// (1) Retailer < - > (*) Shop
retailerEntity.addToMany(shopEntity, retailerId);
}
When I do:
return (ArrayList<Retailer>) mDaoSession.getRetailerDao()
.queryBuilder().list();
I only get contents of the Retailer table itself, however I also need Shop entity values which're null. Only after I call getShops() the entities get filled. I need to fill entities right at the first query. How is it done ?
Thanks.
Use the queryDeep method:
return mDaoSession.getRetailerDao().queryDeep(null);

Categories

Resources