Room Db With Many To Many Relations : Returns Single Entry On Querying For Filtered Data
Solution 1:
I believe that your issue is how you are processing the UiModel list returned from the getFilteredModelList method.
Consider the following methods added for debugging purposes (in this example case, added to MainActivity.java). :-
publicstaticvoidlogUiModel(List<UiModel> uiModelList) {
StringBuilder sb = newStringBuilder();
for (UiModelu: uiModelList) {
sb.append("\n\tUIModel Person ID = " + String.valueOf(u.getPerson().getPresonID()) + " Person Name = " + u.getPerson().getPersonName());
for (Tagt: u.getTags()) {
sb.append("\n\t\tTag ID =" + String.valueOf(t.getTagID()) + " Value = " + t.getTagValue());
}
}
Log.d("UIMODELINFO(LIST)",sb.toString());
}
publicstaticvoidlogUiModel(UiModel uiModel) {
StringBuilder sb = newStringBuilder().append("\nUIMODEL Person ID = " +String.valueOf(uiModel.getPerson().getPresonID()) + " Person Name = " + uiModel.getPerson().getPersonName());
for (Tagt: uiModel.getTags()) {
sb.append("\n\t\tTag ID =" + String.valueOf(t.getTagID()) + " Value = " + t.getTagValue());
}
Log.d("UIMODELINFO",sb.toString());
}
publicstaticvoidlogPersons(List<Person> personList) {
StringBuilder sb = newStringBuilder().append("People are :-");
for (Personp: personList) {
sb.append("\n\tPerson ID is " + String.valueOf(p.getPresonID()) + " Name is" + p.getPersonName());
}
Log.d("PERSONINFO",sb.toString());
}
publicstaticvoidlogTags(List<Tag> tagList) {
StringBuilder sb = newStringBuilder().append("Tags are");
for (Tagt: tagList) {
sb.append("\n\tTag ID is " + String.valueOf(t.getTagID()) + " Value is " + t.getTagValue());
}
Log.d("TAGINFO",sb.toString());
}
And the following changes to the getFilteredModelList method :-
@TransactionpublicList<UiModel> getFilteredModelList(String tag) {
List<UiModel> resultList = newArrayList<>();
long tagID = getTagIdByTagName(tag);
Log.d("GETFLTRMDLLST","Processing TAG where value is " + tag + " ID is " + String.valueOf(tagID));
List<Person> filteredPersonList = getAllPersonsForTagID(tagID);
for (Person p : filteredPersonList) {
Log.d("GETFLTRDMDLLST","Persons are :-");
MainActivity.logPersons(filteredPersonList);
List<Tag> associatedTags = getAllTagsForPerson(p.getPresonID());
Log.d("GETFLTRDMDLLST","Tags are :-");
MainActivity.logTags(associatedTags);
UiModel u = newUiModel(p,associatedTags);
Log.d("GETFLTRDMDLLST","UIModels are :-");
MainActivity.logUiModel(u);
resultList.add(u);
}
return resultList;
}
and the following testing code (again in MainActivity.java) :-
protectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPDB = Room.databaseBuilder(this,PersonDatabase.class,"person.db").allowMainThreadQueries().build();
addDataIfNone();
List<Person> allPeople = mPDB.personDao().getAllPersons();
logPersons(allPeople);
List<Tag> allTags1 = mPDB.personDao().getAllTags();
logTags(allTags1);
List<PersonTagRelation> allPTRs = mPDB.personDao().getAllPersonTagRelations();
logPersonTagRelations(allPTRs);
List<UiModel> uiModelList = mPDB.personDao().getAllAsModelList();
StringBuildersb=newStringBuilder().append("UIMODELS are :-");
for (UiModel u: uiModelList) {
sb.append("\n\tPerson ID = " + String.valueOf(u.getPerson().getPresonID()) + " Name = " + u.getPerson().getPersonName());
for (Tag t: u.getTagList()) {
sb.append("\n\t\tTag ID = " + String.valueOf(t.getTagID()) + " Value = " + t.getTagValue());
}
}
Log.d("UIMODELINFO",sb.toString());
List<Tag> allTags = mPDB.personDao().getAllTags();
List<UiModel> uiListOfModelsViaFilter;
for (Tag t: allTags) {
Log.d("TAGFILTERINF","Filtering with a TAG value of " + t.getTagValue() );
uiListOfModelsViaFilter = mPDB.personDao().getFilteredModelList(String.valueOf(t.getTagValue()));
logUiModel(uiListOfModelsViaFilter);
}
}
privatevoidaddDataIfNone() {
List<Person> people = mPDB.personDao().getAllPersons();
if (people.size() > 0) return;
Person[] peopleToAdd = newPerson[]{
newPerson("A"),
newPerson("B"),
newPerson("C")
};
mPDB.personDao().insertNewPersons(peopleToAdd);
Tag[] tagsToAdd = newTag[] {
newTag("ai"),
newTag("ML"),
newTag("Flutter"),
newTag("JS"),
newTag("Kotlin"),
newTag("Dart")
};
mPDB.personDao().insertNewTags(tagsToAdd);
PersonTagRelation[] ptr = newPersonTagRelation[]{
newPersonTagRelation(1,1),
newPersonTagRelation(1,2),
newPersonTagRelation(2,1),
newPersonTagRelation(3,3)
};
mPDB.personDao().insertNewRelations(ptr);
}
The the more pertinent out shows that for tag ai that persons A and B are extracted :-
06-2411:27:53.3659889-9889/?D/TAGFILTERINF:FilteringwithaTAGvalueofai06-2411:27:53.3669889-9889/?D/GETFLTRMDLLST:ProcessingTAGwherevalueisaiIDis106-2411:27:53.3679889-9889/?D/GETFLTRDMDLLST:Personsare:-06-2411:27:53.3679889-9889/?D/PERSONINFO:Peopleare:-PersonIDis1NameisAPersonIDis2NameisB06-2411:27:53.3679889-9889/?D/GETFLTRDMDLLST:Tagsare:-06-2411:27:53.3679889-9889/?D/TAGINFO:TagsareTagIDis1ValueisaiTagIDis2ValueisML06-2411:27:53.3679889-9889/?D/GETFLTRDMDLLST:UIModelsare:-06-2411:27:53.3679889-9889/?D/UIMODELINFO:UIMODELPersonID=1PersonName=ATagID=1Value=aiTagID=2Value=ML06-2411:27:53.3679889-9889/?D/GETFLTRDMDLLST:Personsare:-06-2411:27:53.3679889-9889/?D/PERSONINFO:Peopleare:-PersonIDis1NameisAPersonIDis2NameisB06-2411:27:53.3679889-9889/?D/GETFLTRDMDLLST:Tagsare:-06-2411:27:53.3679889-9889/?D/TAGINFO:TagsareTagIDis1Valueisai06-2411:27:53.3679889-9889/?D/GETFLTRDMDLLST:UIModelsare:-06-2411:27:53.3679889-9889/?D/UIMODELINFO:UIMODELPersonID=2PersonName=BTagID=1Value=ai06-2411:27:53.3699889-9889/?D/UIMODELINFO(LIST):UIModelPersonID=1PersonName=ATagID=1Value=aiTagID=2Value=MLUIModelPersonID=2PersonName=BTagID=1Value=ai
Edit
This is the full PersonTagRelation class :-
@Entity(primaryKeys = {"personTagIDForPerson","personTagIDForTag"},
foreignKeys = {
@ForeignKey(entity = Person.class, parentColumns = "presonID", childColumns = "personTagIDForPerson"),
@ForeignKey(entity = Tag.class, parentColumns = "tagID", childColumns = "personTagIDForTag"),
})
publicclassPersonTagRelation {
privatelong personTagIDForPerson, personTagIDForTag;
publicPersonTagRelation() {
}
publicPersonTagRelation(long personTagIDForPerson, long personTagIDForTag) {
this.personTagIDForPerson = personTagIDForPerson;
this.personTagIDForTag = personTagIDForTag;
}
publiclonggetPersonTagIDForPerson() {
return personTagIDForPerson;
}
publicvoidsetPersonTagIDForPerson(long personTagIDForPerson) {
this.personTagIDForPerson = personTagIDForPerson;
}
publiclonggetPersonTagIDForTag() {
return personTagIDForTag;
}
publicvoidsetPersonTagIDForTag(long personTagIDForTag) {
this.personTagIDForTag = personTagIDForTag;
}
}
- Note the constructor that takes the two values (and how it is used in the addDataIfNone method).
Solution 2:
As it turns out , it was my silly ui at fault. I was generating a new id every time i add a tag, even if its already present. thus if my DB has the following entries(from what it looks like):
Person --- Tags
A --- ai ,ml
B --- ml
C --- flutter
it was actually this :
id---person id---tag id_person-----------id_tag101 - A11 - ai 101 -- 11102 - B12 - ml 101 -- 12103 - C 13 - ml //! wrong 102 -- 13 //wrong!!
14 - flutter 103 -- 14
My ui was not checking weather a tag existed before adding it as new tag. That's why the getFilteredModelList()
function was not able to generate a list with more than 1 entry. so i ended up writing an extra checker code for that. Also, the dao ended up with the following mini change( an extra onConflict check for all three internal insertion functions):
@DaopublicabstractclassPersonDao {
privatestaticfinalStringTAG="personDao>>";
@Insert(onConflict = OnConflictStrategy.REPLACE)abstractvoidinsertNewPerson(Person... p);
@Insert(onConflict = OnConflictStrategy.REPLACE)abstractvoidinsertNewTag(Tag... t);
@Insert(onConflict = OnConflictStrategy.REPLACE)abstractvoidinsertNewRelation(PersonTagRelation... relation);
...
}
Post a Comment for "Room Db With Many To Many Relations : Returns Single Entry On Querying For Filtered Data"