Комната: заменить курсор SQLite в Дао? - PullRequest
0 голосов
/ 27 мая 2019

У меня есть JobIntentService, который сбрасывает ожидающие уведомления о тревоге из базы данных SQLite. Он использует запрос и курсор для получения дат уведомления из 4 различных столбцов в базе данных. Я конвертирую в базу данных Room и не уверен, как конвертировать курсор в метод Dao. Нужно ли использовать @Transaction, так как я получаю уведомления из нескольких столбцов в базе данных? Буду признателен за любые идеи или мысли о том, как построить в комнате.

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 Ответ

1 голос
/ 28 мая 2019

Я считаю, что @ Transaction оборачивает код в транзакцию.Это уже сделано для всех, кроме @ Query (если @Query не является запросом на обновление / удаление (если это запрос на обновление или удаление, он заключен в транзакцию)).

Я считаю, что вопрос о том, должен ли запрос SELECT быть заключен в транзакцию (@Transaction @Query......), связан с использованием @Relation.Если это так, то списки связанных / связанных элементов / объектов выполняются как отдельные запросы, и, таким образом, выполнение их всех в транзакции обеспечит согласованность данных.Без этого существует вероятность того, что базовые данные могут быть изменены другими транзакциями, и, следовательно, результирующие данные могут быть непоследовательными.

Сказать, что вряд ли это повлияет на использование @ Транзакция там, где этоне требуется и может даже оказать положительное влияние, если он был закодирован там, где он может случайно не быть закодирован.

Конечно, вы всегда можете вернуть Курсор в любом случае, используя Room.Возможно, вы захотите взглянуть на Связывание таблиц с использованием базы данных Room в 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 является эквивалентом Курсора, НО возвращает список объектов 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)

Thisприведет к (для первого запуска): -

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