【发布时间】:2022-02-04 02:51:57
【问题描述】:
总结
我正在制作一个 Android 应用程序,并且我有一个名为 Objective 的 Room 实体,其中存储了它的 startDate 和 endDate。
我想进行一个查询,在其中可以检索“活动”目标,或者换句话说,已经开始但尚未结束的目标。
这是我目前得到的:
查询
@Dao
public interface ObjectiveDao {
/* some code goes here... */
/*
For an objective to be active, its start date should be before the current day,
and its end date should be after the current day.
*/
@Query("SELECT * FROM objectives " +
"WHERE end_date >= strftime('%s', 'now') + 0 " +
"AND start_date <= strftime('%s', 'now') + 0")
List<Objective> getActive();
/* rest of the code goes here... */
}
问题
我的问题在于,当我调用此方法时,会返回一个空列表,而不是预期的活动目标列表 (至少在我尝试运行的各种测试中都发生了这种情况)。
(请参阅底部的编辑以了解此问题出了什么问题。)
额外信息
我还将包括我的Entity、TypeConverter、RoomDatabase 和测试代码,以防万一它可以帮助您解决任何问题。
实体
@Entity(tableName = "objectives")
public class Objective {
@PrimaryKey(autoGenerate = true)
private int id;
/*
I feel like I don't need to
include the whole thing, just the part that matters.
*/
@ColumnInfo(name = "start_date")
private LocalDate startDate;
@ColumnInfo(name = "end_date")
private LocalDate endDate;
public Objective() {
this("", ObjectiveType.OBJECTIVE_DO, 0, LocalDate.now(), LocalDate.now().plusDays(1));
}
public Objective(String title, ObjectiveType type, int quantity, LocalDate startDate, LocalDate endDate) {
this.title = title;
this.type = type;
this.quantity = quantity;
this.startDate = startDate;
this.endDate = endDate;
id = 0;
}
/* rest of the code goes here...*/
}
类型转换器
public class Converters {
@TypeConverter
public static LocalDate fromTimestamp(Long value) {
return value == null ? null : LocalDate.ofEpochDay(value);
}
@TypeConverter
public static Long localDateToTimestamp(LocalDate date) {
return date == null ? null : date.toEpochDay();
}
/* rest of the code goes here...*/
}
房间数据库
@Database(entities = {Objective.class}, version = 1)
@TypeConverters({Converters.class})
public abstract class AppDatabase extends RoomDatabase {
public abstract ObjectiveDao getObjectiveDao();
}
仪器测试
class TestUtil {
static Objective createObjective() {
Objective objective = new Objective();
objective.setTitle("Test Objective");
objective.setType(ObjectiveType.OBJECTIVE_DO);
objective.setQuantity(10);
objective.setStartDate(LocalDate.now());
objective.setEndDate(LocalDate.now().plusDays(1));
return objective;
}
}
public class ObjectivesInstrumentedTest {
private ObjectiveDao objectiveDao;
private AppDatabase db;
@Before
public void createDb() {
Context context = ApplicationProvider.getApplicationContext();
db = Room.inMemoryDatabaseBuilder(context, AppDatabase.class).build();
objectiveDao = db.getObjectiveDao();
}
@After
public void closeDb() throws IOException {
db.close();
}
@Test
public void objectiveIsInsertedIntoDatabase() {
Objective objective = TestUtil.createObjective();
/*
id is set to 1 because, otherwise, Room automatically sets the ID to 1,
and when the objects are compared they do not match. (a value of 0 counts as null).
*/
objective.setId(1);
objectiveDao.insert(objective);
List<Objective> objectives = objectiveDao.getAll();
assertThat(objectives.get(0), equalTo(objective));
}
@Test
public void objectiveIsActive() {
Objective objective = TestUtil.createObjective();
objective.setId(1);
objectiveDao.insert(objective);
List<Objective> objectives = objectiveDao.getActive();
assertThat(objectives.get(0), equalTo(objective));
}
}
如果您想知道,第一个测试运行得很好,但是在运行第二个测试时我得到一个IndexOutOfBoundsException。
希望您能帮我解决这个问题,并提前感谢您抽出时间阅读本文并考虑任何可能的解决方案。
编辑
正如@MikeT 指出的那样,我不是将这些日期存储为秒,也不是作为 unix 时间戳,而是作为自 1970-01-01 以来经过的天数。
【问题讨论】:
-
表格中日期的格式是什么?
-
@forpas 日期存储为 Longs,(如果我没记错的话,技术上是 8 字节长整数),因为 Room 不允许存储“复杂数据”(换句话说,它 doesn't support object references .
标签: java android sqlite android-room