список комнат для Android android Room возвращает только одну запись вместо нескольких записей - PullRequest
0 голосов
/ 11 мая 2018

У меня очень загадочная проблема, когда я пытаюсь выполнить запрос по нескольким таблицам и извлечь из него список данных.

Что происходит

У меня есть запрос, который должен вернуть набор данных, сгруппированных по дате.В моем случае у меня есть запрос в течение 14 дней.Это означает, что запрос должен вернуть 14 записей.То, что на самом деле возвращает фреймворк Room, - это 1 запись.

Как я это тестировал до сих пор

Для своего теста я создал таблицы, как и фреймворк Room для меня..

CREATE TABLE app_usage (
    id INTEGER PRIMARY KEY,
    app_name VARCHAR(50),
    times LONG,
    usage_time_in_seconds INTEGER
);

INSERT INTO app_usage VALUES (0, 'WhatsApp', DATETIME('now'), 17);
INSERT INTO app_usage VALUES (1, 'WhatsApp', DATETIME('now', '+1 day'), 47);
INSERT INTO app_usage VALUES (2, 'WhatsApp', DATETIME('now', '+2 day'), 34);
INSERT INTO app_usage VALUES (3, 'WhatsApp', DATETIME('now', '+3 day'), 65);
INSERT INTO app_usage VALUES (4, 'WhatsApp', DATETIME('now', '+4 day'), 47);
INSERT INTO app_usage VALUES (5, 'WhatsApp', DATETIME('now', '+5 day'), 7);
INSERT INTO app_usage VALUES (6, 'WhatsApp', DATETIME('now', '+6 day'), 92);

CREATE TABLE emotion (
    id INTEGER PRIMARY KEY,
    times LONG,
    value INTEGER
);

INSERT INTO emotion VALUES (0, DATETIME('now'), 2);
INSERT INTO emotion VALUES (1, DATETIME('now', '+1 day'), 0);
INSERT INTO emotion VALUES (2, DATETIME('now', '+2 day'), 1);
INSERT INTO emotion VALUES (3, DATETIME('now', '+3 day'), 0);
INSERT INTO emotion VALUES (4, DATETIME('now', '+4 day'), 2);
INSERT INTO emotion VALUES (5, DATETIME('now', '+5 day'), 3);
INSERT INTO emotion VALUES (6, DATETIME('now', '+6 day'), 4);

CREATE TABLE step_count (
    id INTEGER PRIMARY KEY,
    times LONG,
    value INTEGER
);

INSERT INTO step_count VALUES (0, DATETIME('now'), 4389);
INSERT INTO step_count VALUES (1, DATETIME('now', '+1 day'), 245);
INSERT INTO step_count VALUES (2, DATETIME('now', '+2 day'), 685);
INSERT INTO step_count VALUES (3, DATETIME('now', '+3 day'), 965);
INSERT INTO step_count VALUES (4, DATETIME('now', '+4 day'), 984);
INSERT INTO step_count VALUES (5, DATETIME('now', '+5 day'), 12);

Следующий SQL-запрос - это то же самое, что я использую в своем классе @Dao для извлечения данных.Этот запрос работает (я проверял его на SQLiteOnline ).

SELECT 
MAX(times) as 'Timestamp', 
SUM(usage_time_in_seconds) AS 'UsageTime', 
(SELECT TOTAL(value) FROM step_count WHERE date(times) = DATE(au.times)) AS 'StepCount', 
(SELECT CASE WHEN AVG(value) IS NULL THEN 0.0 ELSE AVG(value) END FROM emotion WHERE DATE(times) = DATE(au.times)) AS 'Emotion'
FROM app_usage au 
WHERE times BETWEEN DATETIME('now', '+1 day') AND DATETIME('now', '+4 day')
GROUP BY DATE(times) 
ORDER BY times DESC

Реализация

Моя реализация класса Dao:

@Dao
@TypeConverters({DateConverter.class})
public interface SummaryDao {

    @Query("SELECT MAX(timestamp) as 'mTimestamp', " +
            "TOTAL(usage_time_in_seconds) as 'mAppUsageTime', " +
            "(SELECT TOTAL(step_count) FROM StepCountEntity WHERE date(timestamp) = date(aue.timestamp)) as 'mSteps', " +
            "(SELECT CASE WHEN AVG(value) IS NULL THEN 0.0 ELSE AVG(value) END FROM EmotionEntity WHERE date(timestamp) = date(aue.timestamp)) as 'mEmotionAvg' " +
            "FROM AppUsageEntity aue " +
            "WHERE timestamp BETWEEN :dateFrom AND :dateTo " +
            "GROUP BY date(timestamp) " +
            "ORDER BY timestamp DESC")
    LiveData<List<SummaryEntity>> getSummaries(Date dateFrom, Date dateTo);
}

Я также заглянул в SummaryDao_Impl.java, где происходит настоящий код.Мой сеанс отладки помог мне выяснить, что Курсор имеет только размер 1 - каждый раз, когда вызывается этот метод.Кроме того, только значения mTimestamp и mAppUsageTime получают реальное значение.Другие переменные остаются пустыми.Что не должно происходить.

Надеюсь, проблема у меня понятна, парень.В противном случае спросите меня.Я очень рад за любую помощь.

Решение

Дата была сохранена как отметка времени (длинная) в базе данных.Это означает, что функция dateite в SQLite не может работать со значением напрямую, поскольку она ожидает секунды, а не миллисекунды.В связи с этим необходимо разделить отметку времени на 1000, чтобы преобразовать ее в секунды.Функция 'date' также нуждается в формате для преобразования метки времени в.Для этого я использовал 'unixepoch'.

@Dao
@TypeConverters({DateConverter.class})
public interface SummaryDao {

    @Query("SELECT MAX(timestamp) as 'mTimestamp', " +
            "TOTAL(usage_time_in_seconds) as 'mAppUsageTime', " +
            "(SELECT TOTAL(step_count) FROM StepCountEntity WHERE date(timestamp/1000, 'unixepoch') = date(aue.timestamp/1000, 'unixepoch')) as 'mSteps', " +
            "(SELECT CASE WHEN AVG(value) IS NULL THEN 0.0 ELSE AVG(value) END FROM EmotionEntity WHERE date(timestamp/1000, 'unixepoch') = date(aue.timestamp/1000, 'unixepoch')) as 'mEmotionAvg' " +
            "FROM AppUsageEntity aue " +
            "WHERE timestamp BETWEEN :dateFrom AND :dateTo " +
            "GROUP BY date(timestamp/1000, 'unixepoch') " +
            "ORDER BY timestamp DESC")
    LiveData<List<SummaryEntity>> getSummaries(Date dateFrom, Date dateTo);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...