我有一个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
);
}
答案 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();
}
例如,可以使用上面的代码(基本上复制了您的代码,但是将提取的数据输出到日志中),例如:-
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())
);
}
}
这将导致(首次运行):-
05-28 14:31:14.587 7211-7211/aso.so56326640 D/ITEMENTRY: notiftime= 100 notiftime2= 200 duedatetime= 500000 randint= 567