【发布时间】:2019-06-23 02:47:07
【问题描述】:
我有 3 个实体 Person、PersonTagRelation 和 Tag:Person 通过多对多关系与标签相关联。
我还有一个用于查询数据库的多个函数的 dao。
大多数事情都运行良好,但我有这个查询,假设创建具有特定标签的用户过滤列表,这似乎不起作用。
例如,如果有 3 个人 A,B,C 对应的标签列表分别为 [ai,ml],[ai],[flutter]。那么我的查询应该返回
[A,B] 当传递标签ai 时。但它只返回[A]。
请检查以下代码,让我知道我哪里出错了:
Person.class
@Entity()
public class Person {
@PrimaryKey
private long presonID;
private String personName;
...
}
标签类
@Entity
public class Tag {
@PrimaryKey
private long tagID;
private String tagValue;
...
}
PersonTagRelation.class
@Entity(primaryKeys = {"personTagIDForPerson","personTagIDForTag"},
foreignKeys = {
@ForeignKey(entity = Person.class, parentColumns = "presonID", childColumns = "personTagIDForPerson"),
@ForeignKey(entity = Tag.class, parentColumns = "tagID", childColumns = "personTagIDForTag"),
})
public class PersonTagRelation {
private long personTagIDForPerson, personTagIDForTag;
...
}
PersonDao.class
@Dao
public abstract class PersonDao {
@Insert abstract void insertNewPerson(Person p);
@Insert abstract void insertNewTag(Tag t);
@Insert abstract void insertNewRelation(PersonTagRelation relation);
@Query("SELECT * FROM Person ORDER BY presonID DESC")
abstract List<Person> getAllPersons();
@Query("SELECT tagID FROM Tag WHERE tagValue=:tag ORDER BY tagID DESC")
abstract long getTagIdByTagName(String tag);
@Query("SELECT * FROM Person" +
" INNER JOIN PersonTagRelation ON Person.presonID=PersonTagRelation.personTagIDForPerson " +
"WHERE PersonTagRelation.personTagIDForTag=:tagID")
abstract List<Person> getAllPersonsForTagID(long tagID);
@Query("SELECT * FROM Tag " +
"INNER JOIN PersonTagRelation ON Tag.tagID=PersonTagRelation.personTagIDForTag " +
"WHERE PersonTagRelation.personTagIDForPerson=:personID")
abstract List<Tag> getAllTagsForPerson(long personID);
@Transaction
public void insertNewPersonTagData(UiModel model) {
insertNewPerson(model.getPerson());
for (Tag t : model.getTags()) {
insertNewTag(t);
insertNewRelation(new PersonTagRelation(model.getPerson().getPresonID(), t.getTagID()));
}
}
@Transaction
public List<UiModel> getFilteredModelList(String tag) {
List<UiModel> resultlist = new ArrayList<>();
long tagID = getTagIdByTagName(tag);
List<Person> filteredPersonList = getAllPersonsForTagID(tagID);
for (Person p : filteredPersonList) {
List<Tag> associatedTags = getAllTagsForPerson(p.getPresonID());
resultlist.add(new UiModel(p, associatedTags));
}
return resultlist;
}
@Transaction
public List<UiModel> getAllAsModelList() {
List<UiModel> modelList = new ArrayList<>();
List<Person> allpersons = getAllPersons();
for (Person p : allpersons) {
List<Tag> associatedTags = getAllTagsForPerson(p.getPresonID());
modelList.add(new UiModel(p, associatedTags));
}
return modelList;
}
UiModel.class
public class UiModel {
private Person person= new Person(System.currentTimeMillis(),"");
private List<Tag> tagList = new ArrayList<>();
public UiModel() {
}
}
图1:getAllAsModelList()的结果
图 2:getFilteredModelList() 当JS 被传递时的结果
更新:
@MikeT 提供的测试套件非常好,但事实证明数据库和查询功能完全正确。有关详细信息,请参阅下面的答案。
【问题讨论】:
-
我将首先使用 Android Studio 的设备文件资源管理器从您的设备或模拟器中复制数据库。接下来,使用 SQLite 客户端(例如,sqlitebrowser.org)来确认您的数据库内容是否符合您的预期。然后,使用该数据库客户端手动执行您的
INNER JOINSQL 并查看是否获得预期结果。如果你这样做了,那么正如 MikeT 所建议的那样,问题可能出在你用 Java 进行的后处理中。如果你不这样做,那么你可以使用 SQL 直到找到满足你想要的 SELECT 语句,然后调整你的 DAO 以匹配。
标签: android database sqlite android-room