室:在Dao中替换SQLite光标?

时间:2019-05-27 15:01:55

标签: android cursor android-sqlite android-room

我有一个JobIntentService,它可以从SQLite数据库重置未决的警报通知。它使用查询和游标从数据库的4个不同列中获取通知日期。我将转换为Room数据库,并且不确定如何将光标转换为Dao方法。因为我要从数据库中的多个列获取通知,所以我需要使用@Transaction吗?感谢您对如何在Room中进行构建的任何见解或想法。

Service

public class Service extends JobIntentService {

static final int JOB_ID = 9;

public static void enqueueWork(Context context, Intent work) {
    enqueueWork(context, RebootService.class, JOB_ID, work);
} 

@Override
protected void onHandleWork(@NonNull Intent intent) {

    AlarmManager alarmManager1;
    Intent brIntent1;
    PendingIntent pendingIntent1;

    SQLiteDB sqLiteDB = SQLiteDB.getInstance(this);
    Calendar cal1 = Calendar.getInstance();

    Cursor cursor = sqLiteDB.resetNotifications(); 

     try {
          if (cursor.getCount() > 0) { 
              cursor.moveToFirst(); 

              int dueDatentimeColumnIndex = cursor.getColumnIndex(ItemContract.ItemEntry.COLUMN_DUEDATENTIME);
              int notifColumnIndex1 = cursor.getColumnIndex(ItemContract.ItemEntry.COLUMN_NOTIFTIME);
              int notif2ColumnIndex2 = cursor.getColumnIndex(ItemContract.ItemEntry.COLUMN_NOTIFTIME2);
              int randColumnIndex1 = cursor.getColumnIndex(ItemContract.ItemEntry.COLUMN_RANDINT);

              while (!cursor.isAfterLast()) {  

                  do {

                      long notifTime1 = cursor.getLong(notifColumnIndex1);
                      int randInt1 = cursor.getInt(randColumnIndex1);
                      cal1.setTime(new Date(notifTime1));

                      // Set up a system AlarmManager to fire a future alarm that sends a Notification
                      // even if the app is in the background or closed.
                      alarmManager1 = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

                      if (cal1.getTimeInMillis() > System.currentTimeMillis()) {                                            
                          brIntent1 = new Intent(this, AlarmReceiver.class);
                       brIntent1.setAction("24Hour");

                       pendingIntent1 = PendingIntent.getBroadcast(this, randInt1, brIntent1,
                                    PendingIntent.FLAG_ONE_SHOT);

                      if (alarmManager1 != null && notifTime1 != -1) {
                          alarmManager1.set(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(), pendingIntent1);
                      }
...       
}

SQLiteDB.java

...
public Cursor resetNotifications() {

   SQLiteDatabase db = getReadableDatabase();

   String[] columns = new String[]{
                ItemContract.ItemEntry.COLUMN_NOTIFTIME,
                ItemContract.ItemEntry.COLUMN_NOTIFTIME2,
                ItemContract.ItemEntry.COLUMN_DUEDATENTIME,
                ItemContract.ItemEntry.COLUMN_RANDINT};

        return db.query(
                TABLE_NAME, 
                columns, // The columns to return
                null,      
                null,   
                null,      
                null,       
                null       
        ); 
}

1 个答案:

答案 0 :(得分:1)

我相信 @Transaction 会将代码包装在交易中。除 @Query 外,所有其他操作都已完成此操作(如果@Query不是更新/删除查询(如果是更新或删除查询,则包装在事务中))。

我认为关于是否应将SELECT查询包装在事务(@Transaction @Query......)中的问题是,如果使用@Relation。如果是这样,则相关/关联项目/对象的列表将作为单独的查询运行,因此在事务中全部运行它们将确保数据一致。如果没有这种可能性,则基础数据可能会被其他事务更改,从而导致最终数据不一致。

说,在不需要的地方使用 @Transaction 几乎不会产生影响,如果在不经意的情况下未将其编码为蜜蜂编码,甚至会产生积极的影响。

当然,您始终可以始终使用Room返回一个Cursor。您不妨看看Associating tables using Room database in Android Studio,其中有一些示例。

根据您的代码,主要是您有一个ItemContract带有ItemEntry的子类,然后ItemEntry的实体可以位于 ItemEntry.java 中,具体如下:-

@Entity
public class ItemEntry {

    @PrimaryKey(autoGenerate = true)
    private long id;
    @ColumnInfo(name = COLUMN_NOTIFTIME)
    private long notiftime;
    @ColumnInfo(name = COLUMN_NOTIFTIME2)
    private long notiftime2;
    @ColumnInfo(name = COLUMN_DUEDATENTIME)
    private long duedatentime;
    @ColumnInfo(name = COLUMN_RANDINT)
    public int randint;

    public ItemEntry(){

    }

    @Ignore
    public ItemEntry(long notiftime, long notiftime2, long duedatentime, int randint) {
        this.notiftime = notiftime;
        this.notiftime2 = notiftime2;
        this.duedatentime = duedatentime;
        this.randint = randint;
    }

    public long getId() {
        return id;
    }

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

    public long getNotiftime() {
        return notiftime;
    }

    public void setNotiftime(long notiftime) {
        this.notiftime = notiftime;
    }

    public long getNotiftime2() {
        return notiftime2;
    }

    public void setNotiftime2(long notiftime2) {
        this.notiftime2 = notiftime2;
    }

    public long getDuedatentime() {
        return duedatentime;
    }

    public void setDuedatentime(long duedatentime) {
        this.duedatentime = duedatentime;
    }

    public int getRandint() {
        return randint;
    }

    public void setRandint(int randint) {
        this.randint = randint;
    }
} 

与接口 ItemEntryDao.java 一样:-

@Dao
interface ItemEntryDao {
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    long[] insertItemEntries(ItemEntry... itemEntries);
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    long insertItemEntry(ItemEntry itemEntry);
    @Update(onConflict = OnConflictStrategy.IGNORE)
    int updateItemEnrties(ItemEntry... itemEntries);
    @Update(onConflict = OnConflictStrategy.IGNORE)
    int updateItemEntry(ItemEntry itemEntry);
    @Delete
    int deleteItemEntries(ItemEntry... itemEntries);
    @Delete
    int deleteItemEntry(ItemEntry itemEntry);
    @Query("SELECT * FROM ItemEntry")
    List<ItemEntry> resetNotifications();
}
  • @Query等同于Cursor,但BUT返回ItemEntry对象的列表。

例如,可以使用上面的代码(基本上复制了您的代码,但是将提取的数据输出到日志中),例如:-

public void onHandleWork() {

    ItemEntry ie = new ItemEntry();
    ie.setNotiftime(100);
    ie.setNotiftime2(200);
    ie.setDuedatentime(500000);
    ie.setRandint(567);
    mDB.getItemEntryDao().insertItemEntry(ie);
    List<ItemEntry> mylist = mDB.getItemEntryDao().resetNotifications();
    for (ItemEntry itementry: mylist) {
        Log.d("ITEMENTRY",
                "\n\tnotiftime= " + String.valueOf(itementry.getNotiftime()) +
                        "\n\tnotiftime2= " + String.valueOf(itementry.getNotiftime2()) +
                        "\n\tduedatetime= " + String.valueOf(itementry.getDuedatentime()) +
                        "\n\trandint= " + String.valueOf(itementry.getRandint())

        );
    }
}
  • mDB是已构建的对象(即@Database类的实例)

这将导致(首次运行):-

05-28 14:31:14.587 7211-7211/aso.so56326640 D/ITEMENTRY:  notiftime= 100
      notiftime2= 200
      duedatetime= 500000
      randint= 567