How to implement Inner Join on Realm DB in android - android

I am searching everywhere but not found the exact way to use Inner Join on Realm DB in Android, check my code
public class UserName extends RealmObject {
private int UserID;
private String UserName;
// Getter Setters
}
public class UserDepartment extends RealmObject {
private int UserID;
private String UserDepartment;
// Getter Setters
}
In SQLite by using following query we easily get data
Select n.UserName, d.UserDepartment
FROM Name n INNER JOIN Department d
ON n.UserID=d.UserID
ORDER BY d.UserDepartment
But how to do same thing on Realm DB to get result...
Thanks in Advance!!

As you may know Realm is a non-relational database and concepts like join belongs for relational database. but if you need to have both UserName and UserDepartment in a single model class there are lots of implementations. but due to my experiences and according to realm constraints in using objects on different threads and updating objects snapshot with realm file, I suggest you to create a new entity, just like this:
class User extends RealmObject{
private int userId;
private UserName username;
private UserDepartment userDepartment;
}
whenever you insert a record into either UserName or UserDepartment you need to insert a record or update existing record in User.

Related

fetch realm data based on dynamic type

I have created following classes in realm for entities like employee , Student and storing its sync status in SyscInfo class
Employee extends RealmObject
_id
name
phone
address
isSync
Student extends RealmObject
_id
name
phone
isSync
SyncInfo extends RealmObject
isSync
timestamp
Now if any emploee or student records are not synced i am setting syncInfo.isSync to false
my background scheduler will check whether we have any offline / not synced data stored in realm db. for that i am firing query for employee and student both.
RealmList<Employee> offlineEmployeeList = realm.where(Employee.class).equalTo("syncInfo.isSync",false).findAllAsync();
RealmList<Student> offlineEmployeeList = realm.where(Student.class).equalTo("syncInfo.isSync",false).findAllAsync();
so what i am looking is , do we have any generalized way to check offline / unsynced data without checking into each entity i.e. Employee and Student.
tomorrow if one more entity got introduced , i again have to fire the same query.
You can create this generic method:
private <T extends RealmModel> RealmResults<T> getNotSynced(Class<T> modelClass) {
return realm.where(modelClass).equalTo("isSynced", false).findAll();
}
And use it like this:
Set<Class<? extends RealmModel>> realmObjectClasses = realm.getConfiguration().getRealmObjectClasses();
ArrayList<RealmResults> notSynched = new ArrayList<>();
for(Class modelClass: realmObjectClasses) {
notSynched.add(getNotSynced(schemaClasses));
}
// Now you have an array of RealmResults with non-synched RealmObjects
About the query method,
I would use the findAll() method and execute the hole thing on a background thread, and not the findAllAsync(), the later requires a more complex synchronisation as I see it.
UPDATE
If not all RealmObjects has the isSynced field, here is what I would do:
RealmObjects has some limitations, but you can implement an empty interface, so I would use that to identify syncable objects and use the getNotSynced method only on them:
Create an empty interface:
public interface Syncable {}
Implement it with all the syncable RealmObjects:
Employee extends RealmObject implements Syncable {
...
}
And then use it to filter the classes in the for loop from before:
for(Class modelClass: realmObjectClasses) {
if (Syncable.class.isAssignableFrom(modelClass)) {
notSynched.add(getNotSynced(schemaClasses));
}
}

Save linked objects Primary key value already exists Relationships

I have just started to use RealmDB and cannot figure out how to save linked object correctly, to implement a sort of foreign key
Here is my main User model.
public class UserModel extends RealmObject {
#PrimaryKey
public Long id;
public String firstName;
public String lastName;
public UserSettings userSettingsModel;
}
UserSettings Model is defined as follows.
public class UserSettingsModel extends RealmObject {
#PrimaryKey
private Long id;
public String email;
public RealmList<Car> cars;
}
And Car is a model itself.
public class Car extends RealmObject {
#PrimaryKey
private Long id;
public String model;
}
The problem is that when I am trying to save UserModel it tries to recreate all objects assigned to it. So before I saving user model I have already creates some Car objects.
I don't need to create them, but to reference like the foreign key in SQL databases. And when I am retrieving a user from the database it should automatically load all related data by primary keys.
Is it possible to achieve such behavior using Realm ?
Thanks for help. Solved this problem by using the copyToRealmOrUpdate method instead of copyToRealm.
You should create a managed object using realm.createObject(clazz, pkValue); if it doesn't exist yet, then set it as value or add it to the RealmList that you get another managed object.
You can also create managed objects from unmanaged objects with copyToRealmOrUpdate() (if the object has a primary key).
And when I am retrieving a user from the database it should automatically load all related data by primary keys.
The RealmList allows access to the related objects, and in fact, is also queryable by calling .where() on it. However, this is not based on primary keys. That feature is tracked under "computed fields".

GreenDao persistance issue

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.

Issue in realm relationships: Many-to-One, it creates duplicate objects

Following the official documents guide: Realm Relationships
I tried to write some code of Many-to-One relationship, and I found some things that are not consistent.
Two POJO Contace.java and Email.java are defined as follows:
public class Email extends RealmObject {
private String address;
private boolean active;
// ... setters and getters left out
}
public class Contact extends RealmObject {
private String name;
private Email email;
// ... setters and getters left out
}
Situation 1: Create a normal Email object and assign to different Contact contactA and contactB.
Email email = new Email();
email.setAddress("realm_test#gmail.com");
email.setActive(true);
Contact contactA = new Contact();
contactA.setName("Bear");
contactA.setEmail(email);
Contact contactB = new Contact();
contactB.setName("Monkey");
contactB.setEmail(email);
realm.beginTransaction();
realm.copyToRealm(contactA);
realm.copyToRealm(contactB);
realm.commitTransaction();
After I call realm.copyToRealm(), two Email objects will be created here. So, when I query Contact from Realm, one Email object will become two different object? I think this is not a Many-to-One relationship anymore, it just become One-to-One relationship.
Situation 2: Call realm.createObject() to create a proxy Email object and two proxy Contact object, and assign email to contactA and contactB.
realm.beginTransaction();
Email email = realm.createObject(Email.class);
email.setAddress("realm_test#gmail.com");
email.setActive(true);
Contact contactA = realm.createObject(Contact.class);
contactA.setName("Bear");
contactA.setEmail(email);
Contact contactB = realm.createObject(Contact.class);
contactB.setName("Monkey");
contactB.setEmail(email);
realm.commitTransaction();
Here we can see just one Email object in the table, and that's what I expected, just as described in the document above.
So, why is there no consistency in situation1 and situation2? Is it a bug in situation1? Or am I missing something?
Realm version(s):0.88.3
Android Studio version:2.0
Looking forward to your reply! Thanks!
Thanks for beeender's answer here: [issue-2730]
This is the expected behaviour.
In the situation1, the email you set to contactA and contactB is a standalone object which is not managed by Realm. So when you copy it to Realm, Realm has no way to know you mean they are the same object. To solve this, you can add a #PrimaryKey to Email and then use copyToRealmOrUpdate. Realm will try to detect if you mean the same email object for both contactA and contactB based on the primary key.
In the situation2, since the email object is managed by Realm, when you call setters, Realm knows that email is actually the same one.
Finally I set a #PrimaryKey both in Contact and Email, as following:
public class Email extends RealmObject {
#PrimaryKey
private String address;
private boolean active;
// ... setters and getters left out
}
public class Contact extends RealmObject {
#PrimaryKey
private String name;
private Email email;
// ... setters and getters left out
}
Then change copyToRealm() to copyToRealmOrUpdate() on contactA and contactB.
realm.beginTransaction();
realm.copyToRealmOrUpdate(contactA);
realm.copyToRealmOrUpdate(contactB);
realm.commitTransaction();
And the relationships betweens Contact and Email was correctly in situation 1.
In the first case two email is created because you are doing copyToRealm two times on different instance.
From the docs Each contact (instance of Contact) have either 0 or 1 email (instance of Email)

Relationship queries in Realm Android

I am new to Realm. I have 3 classes that extends RealmObject whose objects i save to db.
Employee
FamilyMember
and Designation
FamilyMember and Designation is in relationship with Employee like this
public class Employee extends RealmObject{
private String name;
private int age;
private int id;
private Designation designation;
private RealmList <FamilyMember> familyMembers = new RealmList<>();
.
.
.getter setters
.
.
.
}
FamilyMember looks like this
public class FamilyMember extends RealmObject {
private String name;
private String relation;
.
.
.getter setters
.
.
.
}
Now i am able to query a Employee whose FamilyMember has "some" name but i am struggling to find a way to get the list of Employee who has more than four family members.
Can anyone help me? Thanks in advance.
It is unfortunately not easy in the current version of the query language. There is an issue tracking it here: https://github.com/realm/realm-java/issues/1598
Right now you would unfortunately have to find all families and manually filter for those with more than 4.

Categories

Resources