【问题标题】:Android Room Embedded Relation ignores SQL where conditionAndroid Room Embedded Relation 忽略 SQL where 条件
【发布时间】:2018-12-18 18:55:06
【问题描述】:

我是一个 SQL 新手,不明白为什么我的语句会这样。它在 Android Room DAO 中使用并返回不需要的结果。

我在两个表中有这个示例数据:

我有这样的声明:

@Transaction
    @Query("Select Distinct Category.* " +
            "from Category " +
            "inner join Items on Category.ID = Items.Category " +
            "where IsExcluded = 0 " + 
            "order by lower( Category.Name ) asc")
    LiveData<List<CatViewWithItemList>> getCatViewWithItemListGlobal();

结果由一个简单的 POJO 接收:

public class CatViewWithItemList  {

    @Embedded
    public Cat myCat;

    @Relation(parentColumn = "ID",
            entityColumn = "Category") public List<ItemS> ItemList;

问题: 我不明白结果:

为什么第 5 项被退回?它应该被 where 子句排除。我的陈述有错误吗?

MikeT 构建了一个包含相同错误的示例应用程序:

(编辑:我现在放弃了 bool 转换器,Room 似乎在没有它的情况下解析布尔值)或者这可能是由于我死的简单布尔类型转换器造成的吗? 1 和 0 实际上是布尔值的占位符:

@TypeConverter
    public Boolean fromInt(int value) {
        return value == 0 ? false : true;
    }

    @TypeConverter
    public int toInt(Boolean bValue) {
        if (bValue == false) {
            return 0;
        } else {
            return 1;
        }
    }

感谢您的阅读!

编辑: 非常感谢@Angela。她的test 表明sql 语句很好,并且该行为是由sqlite 的特性或接收器pojo 中的嵌入关系引起的。有人对此有什么建议吗?

编辑: MikeT 解释了为什么我想做的事情在房间关系上似乎是不可能的——至少只要没有人证明不同。在他的回答中,他提供了另一种选择。

【问题讨论】:

  • 无。这些结果是调试android studio的手动记录的结果。
  • SQL 查询对我来说看起来不错,尽管它可能与您正在使用的特定 SQL 风格有关。 sqlfiddle.com/#!9/5fcf6b/1
  • 结果与查询不符。例如,Category 表中只有 2 列,而您的输出中有 3 列...您确定您展示了正确的查询和输出吗?
  • @GMB:我明白你的怀疑。我简化了一些事情以突出结果。实际结果是具有一个类别和一个项目列表的三个接收器对象。但是其中一个接收器对象包含一个列表,其项目 id 绝对属于项目 5,并带有排除标志。在 liveData 侦听器在 onChangedEvent 上返回其结果后,我立即进行了调试。当然,我有可能一直忽略同一件事,但我会感到非常惊讶。
  • 确实似乎第 5 项应该从您的初始查询中排除。我不确定您的 SQL 处理代码是如何工作的,因为 pojo 对我来说毫无意义。是否有可能将第 5 项重新列入 b 类项目列表的一部分? @Relation(parentColumn = "ID", entityColumn = "Category") public List ItemList;

标签: sql android-sqlite dao android-room pojo


【解决方案1】:

我认为这可能是由于您的死简单转换器或项目实体的定义方式(我已将 boolean 用于 isexcluded 并且它出现没有转换器也能正常工作)

这是使用我的 Items Entity 版本:-

@Entity(foreignKeys = @ForeignKey(entity = Category.class,parentColumns = "id", childColumns = "category", onDelete =  CASCADE))
public class Items {
    @PrimaryKey(autoGenerate = true)
    private long id;
    private String category;
    private boolean isexcluded;


    public void setCategory(String category) {
        this.category = category;
    }

    public void setId(long id) {
        this.id = id;
    }

    public void setIsexcluded(boolean isexcluded) {
        this.isexcluded = isexcluded;
    }

    public String getCategory() {
        return this.category;
    }

    public long getId() {
        return this.id;
    }

    public boolean isIsexcluded() {
        return this.isexcluded;
    }
}

以及以下类别 DAO:-

@Dao
interface CategoryDAO {
    @Query("SELECT * FROM Category")
    List<Category> getAllcategories();

    @Query("SELECT DISTINCT Category.* " +
            "FROM CATEGORY " +
            "INNER JOIN ITEMS ON category.id = Items.category " +
            "WHERE isexcluded = 0 " +
            "ORDER BY lower(category.name)")
    List<Category> getSpeacial();

    @Query("SELECT DISTINCT Category.* " +
            "FROM CATEGORY " +
            "INNER JOIN ITEMS ON category.id = Items.category " +
            "WHERE isexcluded = 0 " +
            "ORDER BY lower(category.name)")
    List<CatViewWithItemList> getSpeacial2();

    @Insert
    public long[] insertCategory(Category... Category);
}

随着

new Thread(new Runnable() {
            @Override
            public void run() {
                //mRoomDB.categoryDao().insertCategory(initialCategories());
                //mRoomDB.itemsDAO().insertItem(initialItems());
                List<Category> categoryList = mRoomDB.categoryDao().getAllcategories();
                List<Items> itemsList = mRoomDB.itemsDAO().getAllItems();
                for (Category c: categoryList) {
                    Log.d("CATEGORY","Category is " + c.getName() + " refrence is " + c.getId());
                }
                for (Items i: itemsList) {
                    Log.d("ITEM","Item is " + i.getId() + " Category reference is " + i.getCategory() + " Is Excluded is " + Boolean.toString(i.isIsexcluded()));
                }
                List<Category> categoryList2 = mRoomDB.categoryDao().getSpeacial();
                for (Category c: categoryList2) {
                    Log.d("CATEGORY2","Category is " + c.getName() + " reference is " + c.getId());
                }
                List<CatViewWithItemList> catViewWithItemLists = mRoomDB.categoryDao().getSpeacial2();
                for (CatViewWithItemList cvwil: catViewWithItemLists) {
                    Log.d("CATVIEWITEM","Category = " + cvwil.myCat.getId() + " ID = " + cvwil.ItemList.get(0).getId() + " IsExcluded = " + Boolean.toString(cvwil.ItemList.get(0).isIsexcluded()));
                }
            }
        }).start();

并带有:-

public class CatViewWithItemList {

    @Embedded
    public Category myCat;

    @Relation(parentColumn = "id",
            entityColumn = "category")
    public List<Items> ItemList;
}

然后结果是(第一部分基础数据(哦,所以我无法拼写第三个:))):-

2018-12-19 21:47:05.376 2109-2125/? D/CATEGORY: Category is firstname refrence is a
2018-12-19 21:47:05.377 2109-2125/? D/CATEGORY: Category is secondname refrence is b
2018-12-19 21:47:05.377 2109-2125/? D/CATEGORY: Category is thridname refrence is c
2018-12-19 21:47:05.377 2109-2125/? D/ITEM: Item is 1 Category reference is a Is Excluded is false
2018-12-19 21:47:05.377 2109-2125/? D/ITEM: Item is 2 Category reference is c Is Excluded is false
2018-12-19 21:47:05.377 2109-2125/? D/ITEM: Item is 3 Category reference is null Is Excluded is false
2018-12-19 21:47:05.377 2109-2125/? D/ITEM: Item is 4 Category reference is b Is Excluded is false
2018-12-19 21:47:05.377 2109-2125/? D/ITEM: Item is 5 Category reference is b Is Excluded is true
2018-12-19 21:47:05.378 2109-2125/? D/ITEM: Item is 6 Category reference is null Is Excluded is true

然后是两组结果:-

2018-12-19 21:47:05.379 2109-2125/? D/CATEGORY2: Category is firstname reference is a
2018-12-19 21:47:05.380 2109-2125/? D/CATEGORY2: Category is secondname reference is b
2018-12-19 21:47:05.380 2109-2125/? D/CATEGORY2: Category is thridname reference is c


2018-12-19 21:47:05.382 2109-2125/? D/CATVIEWITEM: Category = a ID = 1 IsExcluded = false
2018-12-19 21:47:05.382 2109-2125/? D/CATVIEWITEM: Category = b ID = 4 IsExcluded = false
2018-12-19 21:47:05.382 2109-2125/? D/CATVIEWITEM: Category = c ID = 2 IsExcluded = false

附加

我相信您的问题不在于查询,而在于 CatViewItemList,因为您正在用与该类别相关的所有项目填充项目列表,而与查询无关/之后(我认为,将项目列表嵌入到类别中)。这确实让我感到困惑,因为你真的只想要特定的相关项目(我刚刚在我的代码中抓住了第一个),例如cvwil.ItemList.get(0).isIsexcluded() 幸运的是 4 在 5 之前,所以 isexcluded 显示为 false。

我相信您也许应该从项目中解决这个问题,加入类别,例如像

SELECT * 
FROM Items 
JOIN Category ON Items.category = category.id
WHERE Items.isexcluded = 0 
ORDER BY category.name ASC;

我已更新 gitHub 上的代码来执行此操作(请注意,我已将 Category 表更改为具有 categoryid 而不是 id 的唯一列名。)

现在的结果是(注意添加了另一个类别和另外 2 个项目颠倒顺序,即第一个项目(id 7)被排除为真,然后 id 8 为假):-

2018-12-20 21:39:56.971 9136-9160/so53839431.so53839431roomrelationship D/CATEGORY: Category is firstname Category ID is a
2018-12-20 21:39:56.971 9136-9160/so53839431.so53839431roomrelationship D/CATEGORY: Category is secondname Category ID is b
2018-12-20 21:39:56.971 9136-9160/so53839431.so53839431roomrelationship D/CATEGORY: Category is thirdname Category ID is c
2018-12-20 21:39:56.971 9136-9160/so53839431.so53839431roomrelationship D/CATEGORY: Category is fourthname Category ID is d
2018-12-20 21:39:56.971 9136-9160/so53839431.so53839431roomrelationship D/ITEM: Item is 1 Category reference is a Is Excluded is false
2018-12-20 21:39:56.971 9136-9160/so53839431.so53839431roomrelationship D/ITEM: Item is 2 Category reference is c Is Excluded is false
2018-12-20 21:39:56.971 9136-9160/so53839431.so53839431roomrelationship D/ITEM: Item is 3 Category reference is null Is Excluded is false
2018-12-20 21:39:56.971 9136-9160/so53839431.so53839431roomrelationship D/ITEM: Item is 4 Category reference is b Is Excluded is false
2018-12-20 21:39:56.971 9136-9160/so53839431.so53839431roomrelationship D/ITEM: Item is 5 Category reference is b Is Excluded is true
2018-12-20 21:39:56.971 9136-9160/so53839431.so53839431roomrelationship D/ITEM: Item is 6 Category reference is null Is Excluded is true
2018-12-20 21:39:56.971 9136-9160/so53839431.so53839431roomrelationship D/ITEM: Item is 7 Category reference is d Is Excluded is true
2018-12-20 21:39:56.971 9136-9160/so53839431.so53839431roomrelationship D/ITEM: Item is 8 Category reference is d Is Excluded is false
2018-12-20 21:39:56.972 9136-9160/so53839431.so53839431roomrelationship D/ITEMWITHCAT: Item id =1 Category reference is a Is Excluded is false Referenced Category is a Referenced Category name is firstname
2018-12-20 21:39:56.972 9136-9160/so53839431.so53839431roomrelationship D/ITEMWITHCAT: Item id =2 Category reference is c Is Excluded is false Referenced Category is c Referenced Category name is thirdname
2018-12-20 21:39:56.972 9136-9160/so53839431.so53839431roomrelationship D/ITEMWITHCAT: Item id =4 Category reference is b Is Excluded is false Referenced Category is b Referenced Category name is secondname
2018-12-20 21:39:56.972 9136-9160/so53839431.so53839431roomrelationship D/ITEMWITHCAT: Item id =8 Category reference is d Is Excluded is false Referenced Category is d Referenced Category name is fourthname

【讨论】:

  • 你是对的,不需要布尔转换器。你的 CatViewWithItemList.Class 怎么样?和我一样吗?
  • @Apfelsaft23 我相信我复制了您的 CatViewWithItemList 但会将其添加到答案中。附言如果您认为答案已经回答了问题,请在答案上打勾。
  • 看起来你构建了一个完整的示例应用程序。可以整体上传吗?我仍在努力寻找我的错误。也许是因为我不能在我的情况下使用外键,因为如果类别被删除,我需要项目来生存。非常感谢
  • @Apfelsaft23 代码可以在here 找到你想要的代码在SO53839431ROOMRELATIONSHIP/app/src/main/java/so53839431/so53839431roomrelationship/ 注意 这两行应该在数据加载后注释掉mRoomDB.categoryDao().insertCategory(initialCategories()); mRoomDB.itemsDAO().insertItem(initialItems());否则会因重复而崩溃。
  • 不幸的是,您的示例包含我正在解决的相同错误:条件不能可靠地排除相关列表元素。稍微更改一下 testdata 将显示,只要不排除至少一个列表元素,CatViewWithItemList 就会返回所有元素,无论是否排除(我在主帖中放了一个截图)。你碰巧对这种行为有任何了解吗?还是我应该改变我的计划?再次感谢您的努力!
猜你喜欢
  • 1970-01-01
  • 2020-01-28
  • 1970-01-01
  • 2022-08-02
  • 2018-07-16
  • 1970-01-01
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多