Взаимосвязь Androd Room Embedded игнорирует where condition

Я новичок в 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, кажется, анализирует логическое значение без него) Или это могло быть вызвано моим мертвым преобразователем простого типа для логических значений? Единицы и нули на самом деле являются заполнителями для логических значений:

@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 объясняет, почему то, что я хочу сделать, по-видимому, невозможно с отношениями между комнатами - по крайней мере, пока никто не доказывает иное. В своем ответе он предлагает альтернативу.


person Apfelsaft23    schedule 18.12.2018    source источник
comment
Никто. Эти результаты являются вручную отмеченными результатами отладки студии Android.   -  person Apfelsaft23    schedule 18.12.2018
comment
Мне кажется, что SQL-запрос хорош, хотя это может быть связано с особенностями используемого вами SQL. sqlfiddle.com/#!9/5fcf6b/1   -  person Ángela    schedule 18.12.2018
comment
Результаты не соответствуют запросу. Например, в таблице Category всего 2 столбца, а в вашем выводе - 3 столбца ... Вы уверены, что показываете правильный запрос и вывод?   -  person GMB    schedule 19.12.2018
comment
@GMB: Я вижу ваш скептицизм. Я упростил, чтобы выделить результаты. Фактический результат - три объекта-получателя с одной категорией и списком элементов. Но один из объектов-получателей содержит список с идентификатором элемента, который определенно принадлежит элементу 5 с флагом исключения. Я отлаживал сразу после того, как прослушиватель liveData вернул результат onChangedEvent. Конечно, возможно, я продолжаю упускать из виду одно и то же, но я бы очень удивился.   -  person Apfelsaft23    schedule 19.12.2018
comment
Действительно, кажется, что пункт 5 следует исключить из вашего первоначального запроса. Я не уверен, как работает ваш код обработки SQL, так как pojo для меня ничего не значит. Возможно ли, что элемент 5 будет повторно включен в список элементов категории b? @Relation (parentColumn = ID, entityColumn = Category) public List ‹ItemS› ItemList;   -  person Jack    schedule 19.12.2018
comment
pojo = плоский объект Java. Однако повторное включение - это возможный намек. TBH, я не знаю более глубокую механику @relation   -  person Apfelsaft23    schedule 19.12.2018
comment
Проблема, конечно, не в запросе или базе данных ... Я пометил ваш вопрос pojo, так что надеюсь, что некоторые другие люди SO могут помочь ...   -  person GMB    schedule 19.12.2018


Ответы (1)


Я считаю, что это либо из-за вашего мертвого простого конвертера, либо, возможно, из-за того, что объект Items Entity определен (я использовал boolean для isexcluded, и, похоже, он работает нормально без конвертера).

Это использует мою версию объекта Items: -

@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, поскольку вы заполняете список элементов всеми элементами, относящимися к категории, независимо от запроса или после него (также как я думаю, встраивание список товаров в категории). Это меня смутило, поскольку вам действительно нужен только конкретный связанный элемент (я просто взял 1-й в своем коде), например. cvwil.ItemList.get(0).isIsexcluded() и удача заключалась в том, что 4 идет перед 5, поэтому исключенное значение отображается как ложное.

Я считаю, что вам, возможно, следует подойти к этому из предметов, присоединившись к категории, например. что-то вроде

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

Для этого я обновил код на gitHub (обратите внимание, что я изменил категорию таблица должна иметь уникальное имя столбца categoryid, а не id.)

теперь результаты (обратите внимание, что добавлена ​​еще одна категория и еще 2 элемента в обратном порядке, т.е. первый элемент (идентификатор 7) исключен как истина, затем идентификатор 8 имеет значение false): -

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
person MikeT    schedule 19.12.2018
comment
Вы правы, логический преобразователь не нужен. Как вам нравится ваш CatViewWithItemList.Class lokk? Такой же, как у меня? - person Apfelsaft23; 19.12.2018
comment
@ Apfelsaft23 Мне кажется, я скопировал ваш CatViewWithItemList, но добавлю его в ответ. P.S. отметьте ответ, если вы считаете, что он дал ответ на вопрос. - person MikeT; 20.12.2018
comment
Похоже, вы создали целое примерное приложение. Не могли бы вы загрузить его целиком? Я все еще пытаюсь найти свою ошибку. Возможно, это потому, что я не могу использовать внешний ключ в моем случае, так как мне нужно, чтобы элементы выжили, если категория будет удалена. Большое тебе спасибо - person Apfelsaft23; 20.12.2018
comment
к сожалению, ваш образец содержит ту же ошибку, с которой я борюсь: условия не исключают надежно связанные элементы списка. Небольшое изменение тестовых данных покажет, что как только хотя бы один элемент списка не исключен, CatViewWithItemList вернет все элементы, исключенные или нет (я поместил снимок экрана с этим в основной пост). Вы случайно знаете об этом поведении? Или мне следует изменить свои планы? Еще раз спасибо за старания! - person Apfelsaft23; 20.12.2018
comment
@ Apfelsaft23 Вы пробовали код, который я предоставил совершенно независимо, как отдельный проект? Из того, что вы говорите, приведенный выше пример показывает, что 5 исключено, поскольку это не 0. Удаляли ли вы данные приложения и перестраивали их, когда вы вносили изменения? Возможно, проблема связана с хранящимися данными. - person MikeT; 20.12.2018